diff --git a/.gitsubprojects b/.gitsubprojects
index aec83fbf82037ac84359a52ca4a29784e38e00d4..1fd01b408d3b90bcf3d33d036c2896fb16dc367f 100644
--- a/.gitsubprojects
+++ b/.gitsubprojects
@@ -3,8 +3,8 @@
 #git_subproject( Lexis https://github.com/HBPVis/Lexis.git c24dc07 )
 #git_subproject( gmrvlex https://github.com/vg-lab/gmrvlex.git c20b194 )
 #git_subproject( Brion https://github.com/BlueBrain/Brion.git 073f356 )
-git_subproject( ReTo https://github.com/gmrvvis/ReTo.git 55800024 )
-git_subproject( prefr https://github.com/gmrvvis/prefr.git 5b4b874a )
+git_subproject( ReTo https://github.com/gmrvvis/ReTo.git 211c49af )
 git_subproject( SimIL https://github.com/gmrvvis/SimIL.git a8a56438 )
 git_subproject( scoop https://github.com/gmrvvis/scoop.git b3326cd )
-git_subproject( acuterecorder https://github.com/vg-lab/AcuteRecorder.git 3ae70efa )
+git_subproject( plab git@gitlab.vg-lab.es:g.rial/particlelab.git 04651ec0 )
+git_subproject( acuterecorder https://github.com/vg-lab/AcuteRecorder.git 0b84c2b1 )
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 239b2c06bbdc61b411bbf12b42cfc615f89feb7d..8f852d40857c21b68bf5a7ef1a47100a2e24f997 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,7 @@
 cmake_minimum_required( VERSION 3.1 FATAL_ERROR )
 
 # visimpl project and version
-project( visimpl VERSION 1.7.4 )
+project( visimpl VERSION 1.8.0 )
 set( visimpl_VERSION_ABI 6 )
 
 SET( VISIMPL_LICENSE "GPL")
@@ -69,7 +69,7 @@ common_find_package( Eigen3 REQUIRED SYSTEM)
 common_find_package( HDF5 REQUIRED COMPONENTS C CXX )
 common_find_package( ReTo REQUIRED )
 common_find_package( SimIL REQUIRED )
-common_find_package( prefr REQUIRED )
+common_find_package( plab REQUIRED )
 common_find_package( scoop REQUIRED )
 common_find_package( acuterecorder REQUIRED )
 
@@ -85,7 +85,7 @@ list( APPEND VISIMPL_DEPENDENT_LIBRARIES
   Eigen3
   ReTo
   SimIL
-  prefr
+  plab
   Qt5Core
   Qt5Widgets
   Qt5OpenGL
diff --git a/stackviz/CMakeLists.txt b/stackviz/CMakeLists.txt
index 1889f5ee11f9f03c41d5c94b96e1f0ec54022d36..4e605134fb06ce7aea1b6548ce2aae3e4c087a7b 100644
--- a/stackviz/CMakeLists.txt
+++ b/stackviz/CMakeLists.txt
@@ -5,8 +5,6 @@
 #
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
-add_definitions(-DNEUROLOTS_SKIP_GLEW_INCLUDE )
-
 set(PROJECT_VERSION_ABI ${${PROJECT_NAME}_VERSION_ABI})
  
 set(Name Stackviz)
@@ -45,7 +43,6 @@ set(STACKVIZ_LINK_LIBRARIES
   Qt5::Core
   Qt5::Widgets
   Qt5::OpenGL
-  prefr  
   sumrice
   scoop
   acuterecorder
diff --git a/sumrice/CMakeLists.txt b/sumrice/CMakeLists.txt
index 803c4e531800d75a55f7e16c6781287b4cb2a19f..e0958f04780bcb2e832a9416401f9a95da670696 100644
--- a/sumrice/CMakeLists.txt
+++ b/sumrice/CMakeLists.txt
@@ -28,6 +28,7 @@ set(SUMRICE_PUBLIC_HEADERS
   ConfigureRESTDialog.h
   ConnectRESTDialog.h
   CloseDataDialog.h
+  ColorInterpolator.h
 )
 
 set(SUMRICE_HEADERS
@@ -52,6 +53,7 @@ set(SUMRICE_SOURCES
   ConfigureRESTDialog.cpp
   ConnectRESTDialog.cpp
   CloseDataDialog.cpp
+  ColorInterpolator.cpp
 )
 
 set(SUMRICE_LINK_LIBRARIES
@@ -59,7 +61,6 @@ set(SUMRICE_LINK_LIBRARIES
   Qt5::Widgets
   ReTo
   SimIL
-  prefr
   scoop
 )
 
diff --git a/sumrice/ColorInterpolator.cpp b/sumrice/ColorInterpolator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..160ccfe0890e6fd87a9d75a8f1acfcb96ff24c44
--- /dev/null
+++ b/sumrice/ColorInterpolator.cpp
@@ -0,0 +1,43 @@
+//
+// Created by gaeqs on 6/22/22.
+//
+
+#include "ColorInterpolator.h"
+#include "Utils.h"
+
+
+glm::vec4 ColorInterpolator::getValue( float percentage )
+{
+  if ( data.empty( )) return glm::vec4( 0 );
+  auto first = data[ 0 ];
+  if ( first.first >= percentage ) return first.second;
+
+  auto last = data[ data.size( ) ];
+  if ( percentage >= last.first ) return last.second;
+
+  auto value = visimpl::lower_bound(
+    data.cbegin( ) , data.cend( ) , percentage ,
+    [ ](
+      const std::pair< float , glm::vec4 >& e ,
+      float v )
+    {
+      return e.first < v;
+    } );
+
+  auto next = value + 1;
+  float n = ( percentage - value->first ) / ( next->first - value->first );
+  return glm::mix( value->second , next->second , n );
+}
+
+void ColorInterpolator::insert( float percentage , glm::vec4 value )
+{
+  auto position = visimpl::lower_bound(
+    data.begin( ) , data.end( ) , percentage ,
+    [ ](
+      const std::pair< float , glm::vec4 >& e ,
+      float v )
+    {
+      return e.first < v;
+    } );
+  data.insert( position , std::make_pair( percentage , value ));
+}
\ No newline at end of file
diff --git a/sumrice/ColorInterpolator.h b/sumrice/ColorInterpolator.h
new file mode 100644
index 0000000000000000000000000000000000000000..b5e96ceb1b2c6a004d9097d4bcd99f3a41659dff
--- /dev/null
+++ b/sumrice/ColorInterpolator.h
@@ -0,0 +1,22 @@
+//
+// Created by gaeqs on 6/22/22.
+//
+
+#ifndef VISIMPL_COLORINTERPOLATOR_H
+#define VISIMPL_COLORINTERPOLATOR_H
+
+#include <vector>
+#include <glm/glm.hpp>
+
+struct ColorInterpolator
+{
+
+  std::vector< std::pair< float , glm::vec4>> data;
+
+  glm::vec4 getValue( float percentage );
+
+  void insert( float percentage , glm::vec4 value );
+};
+
+
+#endif //VISIMPL_COLORINTERPOLATOR_H
diff --git a/sumrice/Histogram.cpp b/sumrice/Histogram.cpp
index 1215e986280d6bb28fa1b2f6ba6a0e6d04abd358..ea5b871ca7d1b25c1132ef594fa35f3ff37ee58f 100644
--- a/sumrice/Histogram.cpp
+++ b/sumrice/Histogram.cpp
@@ -30,7 +30,9 @@
 #include <QMouseEvent>
 
 #ifdef VISIMPL_USE_OPENMP
+
 #include <omp.h>
+
 #endif
 
 #include <exception>
@@ -38,110 +40,110 @@
 namespace visimpl
 {
   HistogramWidget::HistogramWidget( )
-  : QFrame( nullptr )
-  , _bins( 50 )
-  , _zoomFactor( 1.5f )
-  , _spikes( nullptr )
-  , _startTime( 0.0f )
-  , _endTime( 0.0f )
-  , _player( nullptr )
-  , _scaleFuncLocal( nullptr )
-  , _scaleFuncGlobal( nullptr )
-  , _colorScaleLocal( T_COLOR_LINEAR )
-  , _colorScaleGlobal( T_COLOR_LOGARITHMIC )
-  , _colorLocal( "#e31a1c" )
-  , _colorGlobal( "#1f78b4" )
-  , _prevColorScaleLocal( T_COLOR_UNDEFINED )
-  , _prevColorScaleGlobal( T_COLOR_UNDEFINED )
-  , _normRule( T_NORM_MAX )
-  , _repMode( T_REP_DENSE )
-  , _fillPlots( true )
-  , _lastMousePosition( nullptr )
-  , _regionPercentage( nullptr )
-  , _paintRegion( false )
-  , _regionWidth( 0.1f )
-  , _gridLinesNumber( 0 )
-  , _paintTimeline( false )
-  , _pixelsPerCharacter( 10 )
-  , _pixelMargin( 5 )
-  , _events( nullptr )
-  , _autoBuildHistogram( true )
-  , _autoCalculateColors( true )
-  {
-    setMinimumHeight(150);
-  }
-
-  HistogramWidget::HistogramWidget( const simil::Spikes& spikes,
-                                 float startTime,
-                                 float endTime )
-  : QFrame( nullptr )
-  , _bins( 50 )
-  , _zoomFactor( 1.5f )
-  , _spikes( &spikes )
-  , _startTime( startTime )
-  , _endTime( endTime )
-  , _player( nullptr )
-  , _scaleFuncLocal( nullptr )
-  , _scaleFuncGlobal( nullptr )
-  , _colorScaleLocal( T_COLOR_LINEAR )
-  , _colorScaleGlobal( T_COLOR_LOGARITHMIC )
-  , _colorLocal( "#e31a1c" )
-  , _colorGlobal( "#1f78b4" )
-  , _prevColorScaleLocal( T_COLOR_UNDEFINED )
-  , _prevColorScaleGlobal( T_COLOR_UNDEFINED )
-  , _normRule( T_NORM_MAX )
-  , _repMode( T_REP_DENSE )
-  , _fillPlots( true )
-  , _lastMousePosition( nullptr )
-  , _regionPercentage( nullptr )
-  , _paintRegion( false )
-  , _regionWidth( 0.1f )
-  , _gridLinesNumber( 0 )
-  , _paintTimeline( false )
-  , _pixelsPerCharacter( 8 )
-  , _pixelMargin( 5 )
-  , _events( nullptr )
-  , _autoBuildHistogram( true )
-  , _autoCalculateColors( true )
+    : QFrame( nullptr )
+    , _bins( 50 )
+    , _zoomFactor( 1.5f )
+    , _spikes( nullptr )
+    , _startTime( 0.0f )
+    , _endTime( 0.0f )
+    , _player( nullptr )
+    , _scaleFuncLocal( nullptr )
+    , _scaleFuncGlobal( nullptr )
+    , _colorScaleLocal( T_COLOR_LINEAR )
+    , _colorScaleGlobal( T_COLOR_LOGARITHMIC )
+    , _colorLocal( "#e31a1c" )
+    , _colorGlobal( "#1f78b4" )
+    , _prevColorScaleLocal( T_COLOR_UNDEFINED )
+    , _prevColorScaleGlobal( T_COLOR_UNDEFINED )
+    , _normRule( T_NORM_MAX )
+    , _repMode( T_REP_DENSE )
+    , _fillPlots( true )
+    , _lastMousePosition( nullptr )
+    , _regionPercentage( nullptr )
+    , _paintRegion( false )
+    , _regionWidth( 0.1f )
+    , _gridLinesNumber( 0 )
+    , _paintTimeline( false )
+    , _pixelsPerCharacter( 10 )
+    , _pixelMargin( 5 )
+    , _events( nullptr )
+    , _autoBuildHistogram( true )
+    , _autoCalculateColors( true )
+  {
+    setMinimumHeight( 150 );
+  }
+
+  HistogramWidget::HistogramWidget( const simil::Spikes& spikes ,
+                                    float startTime ,
+                                    float endTime )
+    : QFrame( nullptr )
+    , _bins( 50 )
+    , _zoomFactor( 1.5f )
+    , _spikes( &spikes )
+    , _startTime( startTime )
+    , _endTime( endTime )
+    , _player( nullptr )
+    , _scaleFuncLocal( nullptr )
+    , _scaleFuncGlobal( nullptr )
+    , _colorScaleLocal( T_COLOR_LINEAR )
+    , _colorScaleGlobal( T_COLOR_LOGARITHMIC )
+    , _colorLocal( "#e31a1c" )
+    , _colorGlobal( "#1f78b4" )
+    , _prevColorScaleLocal( T_COLOR_UNDEFINED )
+    , _prevColorScaleGlobal( T_COLOR_UNDEFINED )
+    , _normRule( T_NORM_MAX )
+    , _repMode( T_REP_DENSE )
+    , _fillPlots( true )
+    , _lastMousePosition( nullptr )
+    , _regionPercentage( nullptr )
+    , _paintRegion( false )
+    , _regionWidth( 0.1f )
+    , _gridLinesNumber( 0 )
+    , _paintTimeline( false )
+    , _pixelsPerCharacter( 8 )
+    , _pixelMargin( 5 )
+    , _events( nullptr )
+    , _autoBuildHistogram( true )
+    , _autoCalculateColors( true )
   {
   }
 
   HistogramWidget::HistogramWidget( const simil::SpikeData& spikeReport )
-  : QFrame( nullptr )
-  , _bins( 50 )
-  , _zoomFactor( 1.5f )
-  , _spikes( &spikeReport.spikes( ))
-  , _startTime( spikeReport.startTime( ))
-  , _endTime( spikeReport.endTime( ))
-  , _player( nullptr )
-  , _scaleFuncLocal( nullptr )
-  , _scaleFuncGlobal( nullptr )
-  , _colorScaleLocal( T_COLOR_LINEAR )
-  , _colorScaleGlobal( T_COLOR_LOGARITHMIC )
-  , _colorLocal( "#e31a1c" )
-  , _colorGlobal( "#1f78b4" )
-  , _prevColorScaleLocal( T_COLOR_UNDEFINED )
-  , _prevColorScaleGlobal( T_COLOR_UNDEFINED )
-  , _normRule( T_NORM_MAX )
-  , _repMode( T_REP_DENSE )
-  , _fillPlots( true )
-  , _lastMousePosition( nullptr )
-  , _regionPercentage( nullptr )
-  , _paintRegion( false )
-  , _regionWidth( 0.1f )
-  , _gridLinesNumber( 0 )
-  , _paintTimeline( false )
-  , _pixelsPerCharacter( 8 )
-  , _pixelMargin( 5 )
-  , _events( nullptr )
-  , _autoBuildHistogram( true )
-  , _autoCalculateColors( true )
-  {
-  }
-
-  void HistogramWidget::Spikes( const simil::Spikes& spikes,
-                                    float startTime,
-                                    float endTime )
+    : QFrame( nullptr )
+    , _bins( 50 )
+    , _zoomFactor( 1.5f )
+    , _spikes( &spikeReport.spikes( ))
+    , _startTime( spikeReport.startTime( ))
+    , _endTime( spikeReport.endTime( ))
+    , _player( nullptr )
+    , _scaleFuncLocal( nullptr )
+    , _scaleFuncGlobal( nullptr )
+    , _colorScaleLocal( T_COLOR_LINEAR )
+    , _colorScaleGlobal( T_COLOR_LOGARITHMIC )
+    , _colorLocal( "#e31a1c" )
+    , _colorGlobal( "#1f78b4" )
+    , _prevColorScaleLocal( T_COLOR_UNDEFINED )
+    , _prevColorScaleGlobal( T_COLOR_UNDEFINED )
+    , _normRule( T_NORM_MAX )
+    , _repMode( T_REP_DENSE )
+    , _fillPlots( true )
+    , _lastMousePosition( nullptr )
+    , _regionPercentage( nullptr )
+    , _paintRegion( false )
+    , _regionWidth( 0.1f )
+    , _gridLinesNumber( 0 )
+    , _paintTimeline( false )
+    , _pixelsPerCharacter( 8 )
+    , _pixelMargin( 5 )
+    , _events( nullptr )
+    , _autoBuildHistogram( true )
+    , _autoCalculateColors( true )
+  {
+  }
+
+  void HistogramWidget::Spikes( const simil::Spikes& spikes ,
+                                float startTime ,
+                                float endTime )
   {
     _spikes = &spikes;
     _startTime = startTime;
@@ -155,7 +157,7 @@ namespace visimpl
     _endTime = spikeReport.endTime( );
   }
 
-  void HistogramWidget::init( unsigned int binsNumber, float zoomFactor_ )
+  void HistogramWidget::init( unsigned int binsNumber , float zoomFactor_ )
   {
     _zoomFactor = zoomFactor_;
     bins( binsNumber );
@@ -169,8 +171,8 @@ namespace visimpl
 
   bool HistogramWidget::empty( void ) const
   {
-    return ( _mainHistogram._maxValueHistogramLocal == 0  ||
-              _mainHistogram._maxValueHistogramGlobal == 0 );
+    return ( _mainHistogram._maxValueHistogramLocal == 0 ||
+             _mainHistogram._maxValueHistogramGlobal == 0 );
   }
 
   void HistogramWidget::Update( THistogram histogramNumber )
@@ -185,13 +187,13 @@ namespace visimpl
   {
     Histogram* histogram = &_mainHistogram;
 
-    if( histogramNumber == T_HIST_FOCUS )
+    if ( histogramNumber == T_HIST_FOCUS )
       histogram = &_focusHistogram;
 
-    const unsigned int histogramSize = histogram->size();
-    std::vector< unsigned int > globalHistogram( histogramSize, 0 );
+    const unsigned int histogramSize = histogram->size( );
+    std::vector< unsigned int > globalHistogram( histogramSize , 0 );
 
-    float totalTime = _endTime - _startTime ;
+    float totalTime = _endTime - _startTime;
 
     bool filter = _filteredGIDs.size( ) > 0;
 
@@ -226,23 +228,26 @@ namespace visimpl
     omp_set_dynamic( 0 );
     omp_set_num_threads( numThreads );
     const auto& references = _spikes->refData( );
-    for( int i = 0; i < static_cast<int>(references.size( )); i++)
+    for ( int i = 0; i < static_cast<int>(references.size( )); i++ )
     {
       simil::TSpikes::const_iterator spikeIt = references[ i ];
 
-      const float endTime = ( i < ( static_cast<int>(references.size()) - 1 )) ?
-                      references[ i + 1]->first :
-                      _endTime;
+      const float endTime = ( i < ( static_cast<int>(references.size( )) - 1 ))
+                            ?
+                            references[ i + 1 ]->first :
+                            _endTime;
 
-      while( spikeIt->first < endTime && spikeIt != _spikes->end( ))
+      while ( spikeIt->first < endTime && spikeIt != _spikes->end( ))
       {
         const float percentage =
-            std::max( 0.0f,
-                      std::min( 1.0f, ( spikeIt->first - _startTime )* invTotalTime ));
+          std::max( 0.0f ,
+                    std::min( 1.0f ,
+                              ( spikeIt->first - _startTime ) * invTotalTime ));
 
-        const unsigned int bin = percentage * (histogramSize - 1);
+        const unsigned int bin = percentage * ( histogramSize - 1 );
 
-        if( !filter || _filteredGIDs.find( spikeIt->second ) != _filteredGIDs.end( ))
+        if ( !filter ||
+             _filteredGIDs.find( spikeIt->second ) != _filteredGIDs.end( ))
         {
           ( *histogram )[ bin ]++;
         }
@@ -254,9 +259,9 @@ namespace visimpl
 #endif // VISIMPL_USE_OPENMP
 
     unsigned int count = 0;
-    for( auto bin: *histogram )
+    for ( auto bin: *histogram )
     {
-      if( bin > histogram->_maxValueHistogramLocal )
+      if ( bin > histogram->_maxValueHistogramLocal )
       {
         histogram->_maxValueHistogramLocal = bin;
       }
@@ -265,11 +270,11 @@ namespace visimpl
 
     histogram->_maxValueHistogramGlobal = histogram->_maxValueHistogramLocal;
 
-    if( filter )
+    if ( filter )
     {
-      for( auto bin : globalHistogram )
+      for ( auto bin: globalHistogram )
       {
-        if( bin > histogram->_maxValueHistogramGlobal )
+        if ( bin > histogram->_maxValueHistogramGlobal )
         {
           histogram->_maxValueHistogramGlobal = bin;
         }
@@ -280,25 +285,25 @@ namespace visimpl
   constexpr float base = 1.0001f;
 
   // All these functions consider a maxValue = 1.0f / <calculated_maxValue >
-  float linearFunc( float value, float invMaxValue )
+  float linearFunc( float value , float invMaxValue )
   {
     return value * invMaxValue;
   }
 
-  float exponentialFunc( float value, float maxValue )
+  float exponentialFunc( float value , float maxValue )
   {
-    return ( powf( base, value - maxValue ));
+    return ( powf( base , value - maxValue ));
   }
 
-  float logarithmicFunc( float value, float invMaxValue )
+  float logarithmicFunc( float value , float invMaxValue )
   {
-    return ( log10f( value) * invMaxValue );
+    return ( log10f( value ) * invMaxValue );
   }
 
-  float maxValueFunc( float maxValue,  TColorScale colorScale )
+  float maxValueFunc( float maxValue , TColorScale colorScale )
   {
     float result = 0.0f;
-    switch( colorScale )
+    switch ( colorScale )
     {
       case T_COLOR_LINEAR:
         result = 1.0f / maxValue;
@@ -307,7 +312,7 @@ namespace visimpl
         result = 1.0f / log10f( maxValue );
         break;
       default:
-        VISIMPL_THROW( "Selected color scale function is not available.")
+      VISIMPL_THROW( "Selected color scale function is not available." )
         break;
     }
 
@@ -318,10 +323,10 @@ namespace visimpl
   {
     Histogram* histogram = &_mainHistogram;
 
-    if( histogramNumber == T_HIST_FOCUS )
+    if ( histogramNumber == T_HIST_FOCUS )
       histogram = &_focusHistogram;
 
-    if( _repMode == T_REP_DENSE )
+    if ( _repMode == T_REP_DENSE )
     {
       QGradientStops stops;
 
@@ -331,27 +336,29 @@ namespace visimpl
       float percentage;
 
       maxValue = _normRule == T_NORM_GLOBAL ?
-                  histogram->_maxValueHistogramGlobal :
-                  histogram->_maxValueHistogramLocal;
+                 histogram->_maxValueHistogramGlobal :
+                 histogram->_maxValueHistogramLocal;
 
-      maxValue = maxValueFunc( maxValue, _normRule == T_NORM_GLOBAL ?
+      maxValue = maxValueFunc( maxValue , _normRule == T_NORM_GLOBAL ?
                                           _colorScaleGlobal :
                                           _colorScaleLocal );
 
-      for( auto bin: *histogram )
+      for ( auto bin: *histogram )
       {
-        percentage = _scaleFuncLocal( float( bin ), maxValue );
-        percentage = std::max< float >( std::min< float > (1.0f, percentage ), 0.0f);
+        percentage = _scaleFuncLocal( float( bin ) , maxValue );
+        percentage = std::max< float >( std::min< float >( 1.0f , percentage ) ,
+                                        0.0f );
 
-        glm::vec4 color = _colorMapper.GetValue( percentage );
-        stops << qMakePair( relativeTime, QColor( color.r, color.g, color.b, color.a ));
+        glm::vec4 color = _colorMapper.getValue( percentage );
+        stops << qMakePair( relativeTime ,
+                            QColor( color.r , color.g , color.b , color.a ));
 
         relativeTime += delta;
       }
 
       histogram->_gradientStops = stops;
     }
-    else if( _repMode == T_REP_CURVE )
+    else if ( _repMode == T_REP_CURVE )
     {
       float invMaxValueLocal;
       float invMaxValueGlobal;
@@ -362,33 +369,33 @@ namespace visimpl
       auxLocal.reserve( histogram->size( ));
       auxGlobal.reserve( histogram->size( ));
 
-      invMaxValueLocal = maxValueFunc( histogram->_maxValueHistogramLocal,
+      invMaxValueLocal = maxValueFunc( histogram->_maxValueHistogramLocal ,
                                        _colorScaleLocal );
 
-      invMaxValueGlobal = maxValueFunc( histogram->_maxValueHistogramGlobal,
+      invMaxValueGlobal = maxValueFunc( histogram->_maxValueHistogramGlobal ,
                                         _colorScaleGlobal );
 
       float currentX;
       float globalY;
       float localY;
       unsigned int counter = 0;
-      const float invBins = 1.0f / float( histogram->size( ) - 1);
+      const float invBins = 1.0f / float( histogram->size( ) - 1 );
 
-      for( auto bin: *histogram )
+      for ( auto bin: *histogram )
       {
         currentX = counter * invBins;
 
         globalY = 0.0f;
         localY = 0.0f;
 
-        if( bin > 0)
+        if ( bin > 0 )
         {
-          globalY = _scaleFuncGlobal( float( bin ), invMaxValueGlobal );
-          localY = _scaleFuncLocal( float( bin ), invMaxValueLocal );
+          globalY = _scaleFuncGlobal( float( bin ) , invMaxValueGlobal );
+          localY = _scaleFuncLocal( float( bin ) , invMaxValueLocal );
         }
 
-        auxGlobal.push_back( QPointF( currentX, 1.0f - globalY ));
-        auxLocal.push_back( QPointF( currentX, 1.0f - localY ));
+        auxGlobal.push_back( QPointF( currentX , 1.0f - globalY ));
+        auxLocal.push_back( QPointF( currentX , 1.0f - localY ));
 
         counter++;
       }
@@ -417,32 +424,32 @@ namespace visimpl
 
   void HistogramWidget::bins( unsigned int binsNumber )
   {
-    if( _bins == binsNumber ) return;
+    if ( _bins == binsNumber ) return;
 
     _bins = binsNumber;
 
     _mainHistogram.clear( );
-    _mainHistogram.resize( _bins, 0 );
+    _mainHistogram.resize( _bins , 0 );
     _mainHistogram._maxValueHistogramLocal = 0;
     _mainHistogram._maxValueHistogramGlobal = 0;
 
-    if( _autoBuildHistogram )
+    if ( _autoBuildHistogram )
       BuildHistogram( T_HIST_MAIN );
 
-    if( _autoCalculateColors )
+    if ( _autoCalculateColors )
       CalculateColors( T_HIST_MAIN );
 
     const unsigned int focusBins = _bins * _zoomFactor;
 
     _focusHistogram.clear( );
-    _focusHistogram.resize( focusBins, 0 );
+    _focusHistogram.resize( focusBins , 0 );
     _focusHistogram._maxValueHistogramLocal = 0;
     _focusHistogram._maxValueHistogramGlobal = 0;
 
-    if( _autoBuildHistogram )
+    if ( _autoBuildHistogram )
       BuildHistogram( T_HIST_FOCUS );
 
-    if( _autoCalculateColors )
+    if ( _autoCalculateColors )
       CalculateColors( T_HIST_FOCUS );
   }
 
@@ -453,14 +460,16 @@ namespace visimpl
 
   void HistogramWidget::zoomFactor( float factor )
   {
-    if(std::abs(_zoomFactor - factor) < std::numeric_limits<float>::epsilon()) return;
+    if ( std::abs( _zoomFactor - factor ) <
+         std::numeric_limits< float >::epsilon( ))
+      return;
 
     _zoomFactor = factor;
 
     const unsigned int focusBins = _bins * _zoomFactor;
 
     _focusHistogram.clear( );
-    _focusHistogram.resize( focusBins, 0 );
+    _focusHistogram.resize( focusBins , 0 );
     _focusHistogram._maxValueHistogramLocal = 0;
     _focusHistogram._maxValueHistogramGlobal = 0;
 
@@ -484,12 +493,12 @@ namespace visimpl
 
   void HistogramWidget::colorScaleLocal( TColorScale scale )
   {
-    if(_colorScaleLocal == scale && _scaleFuncLocal) return;
+    if ( _colorScaleLocal == scale && _scaleFuncLocal ) return;
 
     _prevColorScaleLocal = _colorScaleLocal;
     _colorScaleLocal = scale;
 
-    switch( _colorScaleLocal )
+    switch ( _colorScaleLocal )
     {
       case T_COLOR_LINEAR:
         _scaleFuncLocal = linearFunc;
@@ -498,25 +507,25 @@ namespace visimpl
         _scaleFuncLocal = logarithmicFunc;
         break;
       default:
-        {
-          const auto message = std::string("Invalid TColorScale value ") +
-                               std::to_string(static_cast<int>(scale)) + " " +
-                               std::string(__FILE__) + ":" +
-                               std::to_string(__LINE__);
-          throw std::out_of_range(message.c_str());
-        }
+      {
+        const auto message = std::string( "Invalid TColorScale value " ) +
+                             std::to_string( static_cast<int>(scale)) + " " +
+                             std::string( __FILE__ ) + ":" +
+                             std::to_string( __LINE__ );
+        throw std::out_of_range( message.c_str( ));
+      }
         break;
     }
   }
 
   void HistogramWidget::colorScaleGlobal( TColorScale scale )
   {
-    if(_colorScaleGlobal == scale && _scaleFuncGlobal) return;
+    if ( _colorScaleGlobal == scale && _scaleFuncGlobal ) return;
 
     _prevColorScaleGlobal = _colorScaleGlobal;
     _colorScaleGlobal = scale;
 
-    switch( _colorScaleGlobal )
+    switch ( _colorScaleGlobal )
     {
       case T_COLOR_LINEAR:
         _scaleFuncGlobal = linearFunc;
@@ -525,13 +534,13 @@ namespace visimpl
         _scaleFuncGlobal = logarithmicFunc;
         break;
       default:
-        {
-          const auto message = std::string("Invalid TColorScale value ") +
-                               std::to_string(static_cast<int>(scale)) + " " +
-                               std::string(__FILE__) + ":" +
-                               std::to_string(__LINE__);
-          throw std::out_of_range(message.c_str());
-        }
+      {
+        const auto message = std::string( "Invalid TColorScale value " ) +
+                             std::to_string( static_cast<int>(scale)) + " " +
+                             std::string( __FILE__ ) + ":" +
+                             std::to_string( __LINE__ );
+        throw std::out_of_range( message.c_str( ));
+      }
         break;
     }
   }
@@ -542,7 +551,7 @@ namespace visimpl
   }
 
   void HistogramWidget::normalizeRule(
-      TNormalize_Rule normRule )
+    TNormalize_Rule normRule )
   {
     _normRule = normRule;
   }
@@ -554,21 +563,21 @@ namespace visimpl
 
   void HistogramWidget::gridLinesNumber( unsigned int linesNumber )
   {
-    if(_gridLinesNumber == linesNumber) return;
+    if ( _gridLinesNumber == linesNumber ) return;
 
     _gridLinesNumber = linesNumber;
 
     _mainHistogram._gridLines.clear( );
 
     std::vector< float > gridLines;
-    if( linesNumber > 0 )
+    if ( linesNumber > 0 )
     {
       float current = 0;
       const float delta = 1.0f / float( linesNumber + 1 );
 
       gridLines.push_back( 0.0f );
 
-      for( unsigned int i = 1; i <= linesNumber; ++i )
+      for ( unsigned int i = 1; i <= linesNumber; ++i )
       {
         current += delta;
         gridLines.push_back( current );
@@ -585,7 +594,7 @@ namespace visimpl
   }
 
   void HistogramWidget::representationMode(
-      TRepresentation_Mode repMode )
+    TRepresentation_Mode repMode )
   {
     _repMode = repMode;
   }
@@ -626,14 +635,12 @@ namespace visimpl
     return _focusHistogram._maxValueHistogramGlobal;
   }
 
-  const utils::InterpolationSet< glm::vec4 >&
-  HistogramWidget::colorMapper( void )
+  const ColorInterpolator& HistogramWidget::colorMapper( void )
   {
     return _colorMapper;
   }
 
-  void HistogramWidget::colorMapper(
-      const utils::InterpolationSet< glm::vec4 >& colors )
+  void HistogramWidget::colorMapper( const ColorInterpolator& colors )
   {
     _colorMapper = colors;
   }
@@ -666,9 +673,10 @@ namespace visimpl
   unsigned int HistogramWidget::valueAt( float percentage )
   {
     unsigned int position =
-        std::max( 0.0f, std::min( 1.0f, percentage)) * _mainHistogram.size( );
+      std::max( 0.0f , std::min( 1.0f , percentage )) * _mainHistogram.size( );
 
-    position = std::min(position, static_cast<unsigned int>(_mainHistogram.size() - 1));
+    position = std::min( position ,
+                         static_cast<unsigned int>(_mainHistogram.size( ) - 1));
 
     return _mainHistogram[ position ];
   }
@@ -677,7 +685,8 @@ namespace visimpl
   {
     unsigned int position = percentage * _focusHistogram.size( );
 
-    position = std::min(position, static_cast<unsigned int>(_mainHistogram.size() - 1));
+    position = std::min( position ,
+                         static_cast<unsigned int>(_mainHistogram.size( ) - 1));
 
     return _focusHistogram[ position ];
   }
@@ -726,14 +735,14 @@ namespace visimpl
 
     float percentage = position.x( ) / float( width( ));
 
-    if( event_->modifiers( ) == Qt::ControlModifier ||
-        event_->modifiers( ) == Qt::ShiftModifier )
+    if ( event_->modifiers( ) == Qt::ControlModifier ||
+         event_->modifiers( ) == Qt::ShiftModifier )
     {
-      emit mouseModifierPressed( percentage, event_->modifiers( ));
+      emit mouseModifierPressed( percentage , event_->modifiers( ));
     }
     else
     {
-      emit mousePressed( mapToGlobal( position ), percentage );
+      emit mousePressed( mapToGlobal( position ) , percentage );
     }
   }
 
@@ -742,7 +751,7 @@ namespace visimpl
     QPoint position = event_->pos( );
 
     float percentage = position.x( ) / float( width( ));
-    emit mouseReleased( mapToGlobal( position ), percentage );
+    emit mouseReleased( mapToGlobal( position ) , percentage );
   }
 
   void HistogramWidget::mouseMoveEvent( QMouseEvent* event_ )
@@ -796,21 +805,21 @@ namespace visimpl
     _mainHistogram._cachedLocalRep = QPainterPath( );
     _mainHistogram._cachedGlobalRep = QPainterPath( );
 
-    _mainHistogram._cachedLocalRep.moveTo( 0, height( ) );
-    for( auto point : _mainHistogram._curveStopsLocal )
+    _mainHistogram._cachedLocalRep.moveTo( 0 , height( ));
+    for ( auto point: _mainHistogram._curveStopsLocal )
     {
-      _mainHistogram._cachedLocalRep.lineTo( QPoint( point.x( ) * width( ),
+      _mainHistogram._cachedLocalRep.lineTo( QPoint( point.x( ) * width( ) ,
                                                      point.y( ) * height( )));
     }
-    _mainHistogram._cachedLocalRep.lineTo( width( ), height( ) );
+    _mainHistogram._cachedLocalRep.lineTo( width( ) , height( ));
 
-    _mainHistogram._cachedGlobalRep.moveTo( 0, height( ) );
-    for( auto point : _mainHistogram._curveStopsGlobal )
+    _mainHistogram._cachedGlobalRep.moveTo( 0 , height( ));
+    for ( auto point: _mainHistogram._curveStopsGlobal )
     {
-      _mainHistogram._cachedGlobalRep.lineTo( QPoint( point.x( ) * width( ),
+      _mainHistogram._cachedGlobalRep.lineTo( QPoint( point.x( ) * width( ) ,
                                                       point.y( ) * height( )));
     }
-    _mainHistogram._cachedGlobalRep.lineTo( width( ), height( ) );
+    _mainHistogram._cachedGlobalRep.lineTo( width( ) , height( ));
 
   }
 
@@ -826,42 +835,43 @@ namespace visimpl
 
     QColor penColor;
 
-    if( _repMode == T_REP_DENSE )
+    if ( _repMode == T_REP_DENSE )
     {
-      QLinearGradient gradient( 0, 0, width( ), 0 );
+      QLinearGradient gradient( 0 , 0 , width( ) , 0 );
 
-      QRect area = rect();
+      QRect area = rect( );
 
       gradient.setStops( _mainHistogram._gradientStops );
       QBrush brush( gradient );
 
-      painter.fillRect( area, brush );
+      painter.fillRect( area , brush );
 
-      QLine line( QPoint( 0, currentHeight), QPoint( width( ), currentHeight ));
+      QLine line( QPoint( 0 , currentHeight ) ,
+                  QPoint( width( ) , currentHeight ));
       painter.drawLine( line );
 
-      penColor = QColor( 255, 255, 255 );
+      penColor = QColor( 255 , 255 , 255 );
     }
-    else if( _repMode == T_REP_CURVE )
+    else if ( _repMode == T_REP_CURVE )
     {
       painter.setRenderHint( QPainter::Antialiasing );
 
-      painter.fillRect( rect( ), QBrush( QColor( 255, 255, 255, 255 ),
-                                         Qt::SolidPattern ));
+      painter.fillRect( rect( ) , QBrush( QColor( 255 , 255 , 255 , 255 ) ,
+                                          Qt::SolidPattern ));
 
       QColor globalColor( _colorGlobal );
       QColor localColor( _colorLocal );
 
-      if( _fillPlots )
+      if ( _fillPlots )
       {
         globalColor.setAlpha( 50 );
         localColor.setAlpha( 50 );
 
-        painter.setBrush( QBrush( globalColor, Qt::SolidPattern));
+        painter.setBrush( QBrush( globalColor , Qt::SolidPattern ));
         painter.setPen( Qt::NoPen );
         painter.drawPath( _mainHistogram._cachedGlobalRep );
 
-        painter.setBrush( QBrush( localColor, Qt::SolidPattern));
+        painter.setBrush( QBrush( localColor , Qt::SolidPattern ));
         painter.setPen( Qt::NoPen );
         painter.drawPath( _mainHistogram._cachedLocalRep );
       }
@@ -871,159 +881,165 @@ namespace visimpl
         localColor.setAlpha( 100 );
 
         painter.setBrush( Qt::NoBrush );
-        painter.setPen( QPen( Qt::black, Qt::SolidLine ));
+        painter.setPen( QPen( Qt::black , Qt::SolidLine ));
 
-        QLine line( QPoint( 0, currentHeight), QPoint( width( ), currentHeight ));
+        QLine line( QPoint( 0 , currentHeight ) ,
+                    QPoint( width( ) , currentHeight ));
         painter.drawLine( line );
 
-        painter.setPen( QPen( globalColor, Qt::SolidLine ));
+        painter.setPen( QPen( globalColor , Qt::SolidLine ));
         painter.drawPath( _mainHistogram._cachedGlobalRep );
 
         painter.setBrush( Qt::NoBrush );
-        painter.setPen( QPen( localColor, Qt::SolidLine ));
+        painter.setPen( QPen( localColor , Qt::SolidLine ));
         painter.drawPath( _mainHistogram._cachedLocalRep );
       }
 
-      penColor = QColor( 0, 0, 0 );
+      penColor = QColor( 0 , 0 , 0 );
     }
 
-    if( _mainHistogram._gridLines.size( ) > 0 )
+    if ( _mainHistogram._gridLines.size( ) > 0 )
     {
-      for( auto line : _mainHistogram._gridLines )
+      for ( auto line: _mainHistogram._gridLines )
       {
         const int positionX = line * width( );
 
         QPen pen( penColor );
 
-        if( _paintTimeline )
+        if ( _paintTimeline )
         {
           const float timeValue = ( _endTime - _startTime ) * line + _startTime;
           QString value;
-          if(std::abs(ceilf(timeValue) - timeValue) < std::numeric_limits<float>::epsilon())
+          if ( std::abs( ceilf( timeValue ) - timeValue ) <
+               std::numeric_limits< float >::epsilon( ))
           {
-            value = QString::number(static_cast<int>(timeValue));
+            value = QString::number( static_cast<int>(timeValue));
           }
           else
           {
-            value = QString::number(timeValue, 'f', 2);
+            value = QString::number( timeValue , 'f' , 2 );
           }
 
           const int valueLength = value.length( ) * _pixelsPerCharacter;
 
-          if( width( ) - positionX < valueLength )
+          if ( width( ) - positionX < valueLength )
             _pixelMargin = -valueLength;
-          const QPoint position ( positionX + _pixelMargin, currentHeight * 0.25 );
-          pen.setColor( QColor( 150, 150, 150 ));
+          const QPoint position( positionX + _pixelMargin ,
+                                 currentHeight * 0.25 );
+          pen.setColor( QColor( 150 , 150 , 150 ));
           painter.setPen( pen );
 
           QFont backFont = painter.font( );
-          painter.drawText( position, value );
+          painter.drawText( position , value );
         }
 
-        QLine marker( QPoint( positionX, 0 ), QPoint( positionX, height( )));
-        pen.setColor( QColor( 177, 50, 177 ));
+        QLine marker( QPoint( positionX , 0 ) , QPoint( positionX , height( )));
+        pen.setColor( QColor( 177 , 50 , 177 ));
         painter.setPen( pen );
         painter.drawLine( marker );
       }
     }
 
-    if( _lastMousePosition )
+    if ( _lastMousePosition )
     {
       QPoint localPosition = mapFromGlobal( *_lastMousePosition );
 
-      localPosition.setX( std::min( width( ), std::max( 0, localPosition.x( ))));
-      localPosition.setY( std::min( height( ), std::max( 0, localPosition.y( ))));
+      localPosition.setX(
+        std::min( width( ) , std::max( 0 , localPosition.x( ))));
+      localPosition.setY(
+        std::min( height( ) , std::max( 0 , localPosition.y( ))));
 
       const float percentage = float( localPosition.x( )) / float( width( ));
       const int positionX = localPosition.x( );
       int margin = 5;
 
-      const auto value = valueAt(percentage);
-      QString valueText = QString::number( value, 'f', 3 );
+      const auto value = valueAt( percentage );
+      QString valueText = QString::number( value , 'f' , 3 );
       const int valueLength = valueText.length( ) * 10;
-      if( width( ) - positionX < valueLength )
+      if ( width( ) - positionX < valueLength )
         margin = -valueLength;
 
-      if( _regionPercentage && _paintRegion )
+      if ( _regionPercentage && _paintRegion )
       {
         const int regionPosX = width( ) * ( *_regionPercentage );
         const int regionW = _regionWidth * width( );
-        int start = std::max( 0, regionPosX - regionW );
+        int start = std::max( 0 , regionPosX - regionW );
 
-        if( ( regionPosX + regionW ) > width( ) )
+        if (( regionPosX + regionW ) > width( ))
           start = width( ) - regionW * 2;
 
-        const QRect region( std::max( 0, start ), 0, regionW * 2, height( ));
-        const QBrush brush( QColor( 30, 30, 30, 30 ));
+        const QRect region( std::max( 0 , start ) , 0 , regionW * 2 ,
+                            height( ));
+        const QBrush brush( QColor( 30 , 30 , 30 , 30 ));
 
         painter.setBrush( brush );
-        painter.setPen( QColor( 0, 0, 0, 200 ));
+        painter.setPen( QColor( 0 , 0 , 0 , 200 ));
         painter.drawRect( region );
       }
 
       QPen pen( penColor );
       painter.setPen( pen );
 
-      QPoint position ( positionX + margin, height( ) * 0.75f );
+      QPoint position( positionX + margin , height( ) * 0.75f );
 
-      painter.drawText( position, valueText );
+      painter.drawText( position , valueText );
 
-      if( _paintTimeline )
+      if ( _paintTimeline )
       {
         position.setY( height( ) * 0.25f );
 
         QString timeText( "t=" );
-        timeText.append( QString::number( timeAt( percentage ), 'f', 3));
-        painter.drawText( position, timeText );
+        timeText.append( QString::number( timeAt( percentage ) , 'f' , 3 ));
+        painter.drawText( position , timeText );
       }
 
-      QLine marker( QPoint( positionX, 0 ), QPoint( positionX, height( )));
-      pen.setColor( QColor( 177, 50, 50 ));
+      QLine marker( QPoint( positionX , 0 ) , QPoint( positionX , height( )));
+      pen.setColor( QColor( 177 , 50 , 50 ));
       painter.setPen( pen );
       painter.drawLine( marker );
     }
 
-    if( _events && _repMode == T_REP_CURVE )
+    if ( _events && _repMode == T_REP_CURVE )
     {
-      for( const auto& timeFrame : *_events )
+      for ( const auto& timeFrame: *_events )
       {
-        if( !timeFrame.visible )
+        if ( !timeFrame.visible )
           continue;
 
         QColor color = timeFrame.color;
 
         color.setAlpha( 50 );
-        painter.setBrush( QBrush( color, Qt::SolidPattern));
+        painter.setBrush( QBrush( color , Qt::SolidPattern ));
         painter.setPen( Qt::NoPen );
-        for( const auto& p : timeFrame._cachedCommonRep )
+        for ( const auto& p: timeFrame._cachedCommonRep )
           painter.drawPath( p );
       }
     }
 
-    if( _player )
+    if ( _player )
     {
       const int lineX = _player->GetRelativeTime( ) * width( );
 
-      QLine simMarkerLine( QPoint( lineX, 0), QPoint( lineX, height( )));
+      QLine simMarkerLine( QPoint( lineX , 0 ) , QPoint( lineX , height( )));
 
-      QPen pen( QColor( 0, 0, 0, 255 ));
+      QPen pen( QColor( 0 , 0 , 0 , 255 ));
       painter.setPen( pen );
       painter.drawLine( simMarkerLine );
 
-      if( _paintTimeline )
+      if ( _paintTimeline )
       {
-        const auto value = QString::number(_player->currentTime( ), 'f', 3);
+        const auto value = QString::number( _player->currentTime( ) , 'f' , 3 );
 
         const int valueLength = value.length( ) * _pixelsPerCharacter;
-        if( width( ) - lineX < valueLength )
+        if ( width( ) - lineX < valueLength )
           _pixelMargin = -valueLength;
-        QPoint position ( lineX + _pixelMargin, height( ) * 0.5f );
-        pen.setColor( QColor( 150, 150, 150 ));
+        QPoint position( lineX + _pixelMargin , height( ) * 0.5f );
+        pen.setColor( QColor( 150 , 150 , 150 ));
         painter.setPen( pen );
 
         QFont backFont = painter.font( );
 
-        painter.drawText( position, value );
+        painter.drawText( position , value );
       }
     }
   }
diff --git a/sumrice/Histogram.h b/sumrice/Histogram.h
index 1bb5a547302729f568ed7aabb37f460ea15d0089..e2def27bdf890b3c22e2d5c0d031d5e9a982798b 100644
--- a/sumrice/Histogram.h
+++ b/sumrice/Histogram.h
@@ -23,7 +23,6 @@
 #ifndef __HISTOGRAM_H__
 #define __HISTOGRAM_H__
 
-#include <prefr/prefr.h>
 #include <simil/simil.h>
 #include <sumrice/api.h>
 
@@ -31,6 +30,7 @@
 
 #include <QFrame>
 
+#include "ColorInterpolator.h"
 #include "types.h"
 
 namespace visimpl
@@ -137,8 +137,8 @@ namespace visimpl
     unsigned int focusMaxLocal( void ) const;
     unsigned int focusMaxGlobal( void ) const;
 
-    const utils::InterpolationSet< glm::vec4 >& colorMapper( void );
-    void colorMapper(const utils::InterpolationSet< glm::vec4 >& colors );
+    const ColorInterpolator& colorMapper( void );
+    void colorMapper(const ColorInterpolator& colors );
 
     const QGradientStops& gradientStops( void );
 
@@ -214,7 +214,7 @@ signals:
 
     bool _fillPlots;
 
-    utils::InterpolationSet< glm::vec4 > _colorMapper;
+    ColorInterpolator _colorMapper;
 
     GIDUSet _filteredGIDs;
 
diff --git a/sumrice/Summary.cpp b/sumrice/Summary.cpp
index 75f57a45e5652a2f17a35e3f1d168d6b89fb2544..dfe0c2da1d237f6bb5a98aa13f6453dd14269120 100644
--- a/sumrice/Summary.cpp
+++ b/sumrice/Summary.cpp
@@ -527,12 +527,12 @@ namespace visimpl
     _mainHistogram->setMinimumWidth( _sizeChartHorizontal );
     _mainHistogram->simPlayer( _player );
 
-    TColorMapper colorMapper;
-    colorMapper.Insert( 0.0f, glm::vec4( 157, 206, 111, 255 ));
-    colorMapper.Insert( 0.25f, glm::vec4( 125, 195, 90, 255 ));
-    colorMapper.Insert( 0.50f, glm::vec4( 109, 178, 113, 255 ));
-    colorMapper.Insert( 0.75f, glm::vec4( 76, 165, 86, 255 ));
-    colorMapper.Insert( 1.0f, glm::vec4( 63, 135, 61, 255 ));
+    ColorInterpolator colorMapper;
+    colorMapper.insert( 0.0f, glm::vec4( 157, 206, 111, 255 ));
+    colorMapper.insert( 0.25f, glm::vec4( 125, 195, 90, 255 ));
+    colorMapper.insert( 0.50f, glm::vec4( 109, 178, 113, 255 ));
+    colorMapper.insert( 0.75f, glm::vec4( 76, 165, 86, 255 ));
+    colorMapper.insert( 1.0f, glm::vec4( 63, 135, 61, 255 ));
 
     _mainHistogram->colorMapper( colorMapper );
 
diff --git a/sumrice/Summary.h b/sumrice/Summary.h
index fa1e177487f0af5bc01953b15c27ac0c4b0cd09b..d536a61fc3062a3cdea9cafab985554a9e18c631 100644
--- a/sumrice/Summary.h
+++ b/sumrice/Summary.h
@@ -23,7 +23,6 @@
 #ifndef __SIMULATIONSUMMARYWIDGET_H__
 #define __SIMULATIONSUMMARYWIDGET_H__
 
-#include <prefr/prefr.h>
 #include <simil/simil.h>
 #include <scoop/scoop.h>
 #include <sumrice/api.h>
diff --git a/sumrice/TransferFunctionWidget.h b/sumrice/TransferFunctionWidget.h
index 818363ca12064a1be744ad0842938aa4971d0932..e4a0b96b3a5d1678a7681e20dd823bf3e754fa6c 100644
--- a/sumrice/TransferFunctionWidget.h
+++ b/sumrice/TransferFunctionWidget.h
@@ -27,9 +27,6 @@
 #include <sumrice/api.h>
 #include <sumrice/types.h>
 
-// Preft
-#include <prefr/prefr.h>
-
 // Qt
 #include <QWidget>
 
diff --git a/sumrice/Utils.cpp b/sumrice/Utils.cpp
index 0a050dc44c377162ab8e267949fbd6ccb5f18f1b..6a6ada056930331e4f973481ed55fea748f4b5a5 100644
--- a/sumrice/Utils.cpp
+++ b/sumrice/Utils.cpp
@@ -27,34 +27,68 @@
 #include <algorithm>
 #include <cctype>
 
+#include <glm/glm.hpp>
+#include "scoop/Color.h"
+
 //----------------------------------------------------------------------------
-bool visimpl::isValidIPAddress(const std::string &address)
+bool visimpl::isValidIPAddress( const std::string& address )
 {
   std::string address_c = address;
-  std::for_each(address_c.begin(), address_c.end(), tolower);
+  std::for_each( address_c.begin( ) , address_c.end( ) , tolower );
+
+  if ( address_c.length( ) < 7 || address_c.length( ) > 15 ) return false;
+  if ( address_c.compare( "localhost" ) == 0 ) return true;
+
+  char tail[16];
+  tail[ 0 ] = 0;
+
+  unsigned int parts[4];
+  int c = sscanf( address_c.c_str( ) , "%3u.%3u.%3u.%3u%s" , &parts[ 0 ] ,
+                  &parts[ 1 ] , &parts[ 2 ] , &parts[ 3 ] , tail );
+
+  if ( c != 4 || tail[ 0 ] )
+    return false;
+
+  for ( int i = 0; i < 4; i++ )
+    if ( parts[ i ] > 255 )
+      return false;
 
-  if(address_c.length() < 7 || address_c.length() > 15) return false;
-  if(address_c.compare("localhost") == 0) return true;
+  return true;
+}
+
+std::pair< QColor , QColor > visimpl::generateColorPair(
+  const scoop::Color& color )
+{
+  constexpr float invRGBInt = 1.0f / 255;
+  constexpr float brightFactor = 0.4f;
+  constexpr float darkFactor = 1.0f - brightFactor;
 
-   char tail[16];
-   tail[0] = 0;
+  const glm::vec4 baseColor( color.red( ) * invRGBInt ,
+                             color.green( ) * invRGBInt ,
+                             color.blue( ) * invRGBInt , 0.6f );
 
-   unsigned int parts[4];
-   int c = sscanf(address_c.c_str(), "%3u.%3u.%3u.%3u%s", &parts[0], &parts[1], &parts[2], &parts[3], tail);
+  const QColor firstColor = QColor( baseColor.r * 255 ,
+                  baseColor.g * 255 ,
+                  baseColor.b * 255 ,
+                  baseColor.a * 255 );
 
-   if (c != 4 || tail[0])
-       return false;
+  const glm::vec4 darkColor =
+    ( baseColor * brightFactor ) +
+    ( glm::vec4( 0.1f , 0.1f , 0.1f , 0.4f ) * darkFactor );
 
-   for (int i = 0; i < 4; i++)
-       if (parts[i] > 255)
-           return false;
+  const QColor darkqColor = QColor( darkColor.r * 255 ,
+                                    darkColor.g * 255 ,
+                                    darkColor.b * 255 ,
+                                    darkColor.a * 255 );
 
-   return true;
+  return std::make_pair( firstColor , darkqColor );
 }
 
+
 #ifdef VISIMPL_USE_ZEROEQ
+
 //----------------------------------------------------------------------------
-visimpl::ZeroEQConfig& visimpl::ZeroEQConfig::instance()
+visimpl::ZeroEQConfig& visimpl::ZeroEQConfig::instance( )
 {
   static ZeroEQConfig eqConfig;
 
@@ -62,244 +96,276 @@ visimpl::ZeroEQConfig& visimpl::ZeroEQConfig::instance()
 }
 
 //----------------------------------------------------------------------------
-void visimpl::ZeroEQConfig::connect(const std::string &s)
+void visimpl::ZeroEQConfig::connect( const std::string& s )
 {
-  if(m_subscriber || m_publisher)
+  if ( m_subscriber || m_publisher )
   {
-    const auto message = std::string("ZeroEQ Already connected. ") + __FILE__ + ":" + std::to_string(__LINE__);
-    throw std::runtime_error(message);
+    const auto message =
+      std::string( "ZeroEQ Already connected. " ) + __FILE__ + ":" +
+      std::to_string( __LINE__ );
+    throw std::runtime_error( message );
   }
 
-  if(s.compare(zeroeq::NULL_SESSION) == 0)
+  if ( s.compare( zeroeq::NULL_SESSION ) == 0 )
   {
-    const auto message = std::string("Invalid NULL_SESSION connection, missing host and port. ") + __FILE__ + ":" + std::to_string(__LINE__);
-    throw std::runtime_error(message);
+    const auto message = std::string(
+      "Invalid NULL_SESSION connection, missing host and port. " ) + __FILE__ +
+                         ":" + std::to_string( __LINE__ );
+    throw std::runtime_error( message );
   }
 
-  m_session = s.empty() ? zeroeq::DEFAULT_SESSION : s;
+  m_session = s.empty( ) ? zeroeq::DEFAULT_SESSION : s;
 
   try
   {
-    m_subscriber = std::make_shared<zeroeq::Subscriber>(m_session);
-    m_publisher = std::make_shared<zeroeq::Publisher>(m_session);
-    m_host = m_publisher->getURI().getHost();
-    m_port = m_publisher->getURI().getPort();
+    m_subscriber = std::make_shared< zeroeq::Subscriber >( m_session );
+    m_publisher = std::make_shared< zeroeq::Publisher >( m_session );
+    m_host = m_publisher->getURI( ).getHost( );
+    m_port = m_publisher->getURI( ).getPort( );
   }
-  catch(const std::exception &e)
+  catch ( const std::exception& e )
   {
-    std::cerr << "Exception in ZeroEQConfig when connecting to session " << m_session << std::endl;
+    std::cerr << "Exception in ZeroEQConfig when connecting to session "
+              << m_session << std::endl;
     std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
-    disconnect();
+    disconnect( );
     throw;
   }
 
-  print();
+  print( );
 }
 
 //----------------------------------------------------------------------------
-void visimpl::ZeroEQConfig::connect(const std::string &h, const uint16_t p, bool invert)
+void visimpl::ZeroEQConfig::connect( const std::string& h , const uint16_t p ,
+                                     bool invert )
 {
-  if(m_subscriber || m_publisher)
+  if ( m_subscriber || m_publisher )
   {
-    const auto message = std::string("ZeroEQ Already connected. ") + __FILE__ + ":" + std::to_string(__LINE__);
-    throw std::runtime_error(message);
+    const auto message =
+      std::string( "ZeroEQ Already connected. " ) + __FILE__ + ":" +
+      std::to_string( __LINE__ );
+    throw std::runtime_error( message );
   }
 
   m_host = h;
   m_port = p;
   m_session = zeroeq::NULL_SESSION;
 
-  if(!isValidIPAddress(m_host))
+  if ( !isValidIPAddress( m_host ))
   {
-    const auto message = std::string("Invalid host address for NULL_SESSION. ") + __FILE__ + ":" + std::to_string(__LINE__);
-    throw std::runtime_error(message);
+    const auto message =
+      std::string( "Invalid host address for NULL_SESSION. " ) + __FILE__ +
+      ":" + std::to_string( __LINE__ );
+    throw std::runtime_error( message );
   }
 
-  if(m_port < 1024)
+  if ( m_port < 1024 )
   {
-    const auto message = std::string("Invalid port for NULL_SESSION. ") + __FILE__ + ":" + std::to_string(__LINE__);
-    throw std::runtime_error(message);
+    const auto message =
+      std::string( "Invalid port for NULL_SESSION. " ) + __FILE__ + ":" +
+      std::to_string( __LINE__ );
+    throw std::runtime_error( message );
   }
 
   zeroeq::URI uri_subscriber;
-  uri_subscriber.setHost(m_host);
-  uri_subscriber.setPort(m_port + (invert ? 1:0));
+  uri_subscriber.setHost( m_host );
+  uri_subscriber.setPort( m_port + ( invert ? 1 : 0 ));
 
   zeroeq::URI uri_publisher;
-  uri_publisher.setHost(m_host);
-  uri_publisher.setPort(m_port + (!invert ? 1:0));
+  uri_publisher.setHost( m_host );
+  uri_publisher.setPort( m_port + ( !invert ? 1 : 0 ));
 
   try
   {
-    m_publisher = std::make_shared<zeroeq::Publisher>(uri_publisher, m_session);
-    m_subscriber = std::make_shared<zeroeq::Subscriber>(uri_subscriber);
+    m_publisher = std::make_shared< zeroeq::Publisher >( uri_publisher ,
+                                                         m_session );
+    m_subscriber = std::make_shared< zeroeq::Subscriber >( uri_subscriber );
   }
-  catch(const std::exception &e)
+  catch ( const std::exception& e )
   {
-    std::cerr << "Exception in ZeroEQConfig when connecting to session " << m_session << std::endl;
+    std::cerr << "Exception in ZeroEQConfig when connecting to session "
+              << m_session << std::endl;
     std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
-    disconnect();
+    disconnect( );
     throw;
   }
 
-  print();
+  print( );
 }
 
 //----------------------------------------------------------------------------
-void visimpl::ZeroEQConfig::print() const
+void visimpl::ZeroEQConfig::print( ) const
 {
   zeroeq::URI uri;
 
   std::cout << "ZeroEQConfig -> ";
-  if(!m_publisher || !m_subscriber)
+  if ( !m_publisher || !m_subscriber )
   {
     std::cout << "not connected." << std::endl;
   }
   else
   {
-    std::string session = m_session == zeroeq::NULL_SESSION ? "NULL_SESSION" : m_session;
-    session = m_session == zeroeq::DEFAULT_SESSION ? "DEFAULT_SESSION" : session;
-
-    std::cout << "publisher uri: " << m_host << ":" << m_port << " - subscriber to session: " << session << " - "
-              << "receiver loop: " << (m_run ? "":"not ") << "running." << std::endl;
+    std::string session =
+      m_session == zeroeq::NULL_SESSION ? "NULL_SESSION" : m_session;
+    session =
+      m_session == zeroeq::DEFAULT_SESSION ? "DEFAULT_SESSION" : session;
+
+    std::cout << "publisher uri: " << m_host << ":" << m_port
+              << " - subscriber to session: " << session << " - "
+              << "receiver loop: " << ( m_run ? "" : "not " ) << "running."
+              << std::endl;
   }
 }
 
 //----------------------------------------------------------------------------
-void visimpl::ZeroEQConfig::disconnect()
+void visimpl::ZeroEQConfig::disconnect( )
 {
   m_publisher = nullptr;
   m_subscriber = nullptr;
-  m_session.clear();
-  m_host.clear();
+  m_session.clear( );
+  m_host.clear( );
   m_port = 0;
-  stopReceiveLoop();
+  stopReceiveLoop( );
 }
 
 //----------------------------------------------------------------------------
-visimpl::ZeroEQConfig::~ZeroEQConfig()
+visimpl::ZeroEQConfig::~ZeroEQConfig( )
 {
-  disconnect();
+  disconnect( );
   std::cout << "ZeroEQConfig -> disconnected." << std::endl;
 }
 
 //----------------------------------------------------------------------------
-void visimpl::ZeroEQConfig::connectNullSession()
+void visimpl::ZeroEQConfig::connectNullSession( )
 {
-  if(m_subscriber || m_publisher)
+  if ( m_subscriber || m_publisher )
   {
-    const auto message = std::string("ZeroEQ Already connected. ") + __FILE__ + ":" + std::to_string(__LINE__);
-    throw std::runtime_error(message);
+    const auto message =
+      std::string( "ZeroEQ Already connected. " ) + __FILE__ + ":" +
+      std::to_string( __LINE__ );
+    throw std::runtime_error( message );
   }
 
   m_session = zeroeq::NULL_SESSION;
   m_host = "127.0.0.1";
 
-  for(const int port: PORTS)
+  for ( const int port: PORTS )
   {
     try
     {
       m_port = port;
 
       zeroeq::URI uri;
-      uri.setHost(m_host);
-      uri.setPort(m_port);
+      uri.setHost( m_host );
+      uri.setPort( m_port );
 
       std::cout << "ZeroEQ: try publisher in port " << port << std::endl;
-      m_publisher = std::make_shared<zeroeq::Publisher>(uri, m_session);
+      m_publisher = std::make_shared< zeroeq::Publisher >( uri , m_session );
       break;
     }
-    catch(...)
+    catch ( ... )
     {
       // nothing to do, unable to create a publisher in the
       // used port, use next port until we run out of ports.
     }
   }
 
-  if(!m_publisher)
+  if ( !m_publisher )
   {
-    std::cerr << "Exception in ZeroEQConfig when connecting to session " << m_session << std::endl;
+    std::cerr << "Exception in ZeroEQConfig when connecting to session "
+              << m_session << std::endl;
     std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
-    disconnect();
-    const auto message = std::string("ZeroEQ unable to publish in any of the known ports. ") + __FILE__ + ":" + std::to_string(__LINE__);
-    throw std::runtime_error(message);
+    disconnect( );
+    const auto message =
+      std::string( "ZeroEQ unable to publish in any of the known ports. " ) +
+      __FILE__ + ":" + std::to_string( __LINE__ );
+    throw std::runtime_error( message );
   }
 
   zeroeq::URIs uris;
 
   std::string subscriberPorts;
-  for(const int port: PORTS)
+  for ( const int port: PORTS )
   {
-    if(port == m_publisher->getURI().getPort())
+    if ( port == m_publisher->getURI( ).getPort( ))
       continue;
 
     zeroeq::URI uri;
-    uri.setHost(m_host);
-    uri.setPort(port);
+    uri.setHost( m_host );
+    uri.setPort( port );
 
-    uris.push_back(uri);
+    uris.push_back( uri );
 
-    subscriberPorts += subscriberPorts.empty() ? "":",";
-    subscriberPorts += std::to_string(port);
+    subscriberPorts += subscriberPorts.empty( ) ? "" : ",";
+    subscriberPorts += std::to_string( port );
   }
 
   try
   {
-    std::cout << "ZeroEQ: try to subscribe to ports " << subscriberPorts << std::endl;
-    m_subscriber = std::make_shared<zeroeq::Subscriber>(uris);
+    std::cout << "ZeroEQ: try to subscribe to ports " << subscriberPorts
+              << std::endl;
+    m_subscriber = std::make_shared< zeroeq::Subscriber >( uris );
   }
-  catch(std::exception &e)
+  catch ( std::exception& e )
   {
-    std::cerr << "Exception in ZeroEQConfig when connecting to session " << m_session << std::endl;
+    std::cerr << "Exception in ZeroEQConfig when connecting to session "
+              << m_session << std::endl;
     std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
-    disconnect();
+    disconnect( );
     throw;
   }
 
-  print();
+  print( );
 }
 
 //----------------------------------------------------------------------------
-void visimpl::ZeroEQConfig::startReceiveLoop()
+void visimpl::ZeroEQConfig::startReceiveLoop( )
 {
-  if(!m_thread && m_subscriber)
+  if ( !m_thread && m_subscriber )
   {
     std::cout << "ZeroEQConfig STARTS TREAD" << std::endl;
     m_run = true;
-    m_thread = std::make_shared<std::thread>([this]( )
-      {
-        while ( m_run )
-        {
-          try
-          {
-            if(m_subscriber)
-            {
-              m_subscriber->receive( 10000 );
-            }
-          }
-          // exception in zmq_poll
-          catch(const std::exception &e)
-          {
-            std::cerr << "ZeroEQConfig STOPS LISTENING TREAD because exception: " << e.what() << std::endl;
-            m_run = false;
-          }
-          catch(...)
-          {
-            std::cerr << "ZeroEQConfig STOPS LISTENING TREAD because unknown exception." << std::endl;
-            m_run = false;
-          }
-        }
-      });
+    m_thread = std::make_shared< std::thread >( [ this ]( )
+                                                {
+                                                  while ( m_run )
+                                                  {
+                                                    try
+                                                    {
+                                                      if ( m_subscriber )
+                                                      {
+                                                        m_subscriber->receive(
+                                                          10000 );
+                                                      }
+                                                    }
+                                                      // exception in zmq_poll
+                                                    catch (
+                                                      const std::exception& e )
+                                                    {
+                                                      std::cerr
+                                                        << "ZeroEQConfig STOPS LISTENING TREAD because exception: "
+                                                        << e.what( )
+                                                        << std::endl;
+                                                      m_run = false;
+                                                    }
+                                                    catch ( ... )
+                                                    {
+                                                      std::cerr
+                                                        << "ZeroEQConfig STOPS LISTENING TREAD because unknown exception."
+                                                        << std::endl;
+                                                      m_run = false;
+                                                    }
+                                                  }
+                                                } );
   }
 }
 
 //----------------------------------------------------------------------------
-void visimpl::ZeroEQConfig::stopReceiveLoop()
+void visimpl::ZeroEQConfig::stopReceiveLoop( )
 {
-  if(m_run)
+  if ( m_run )
   {
     m_run = false;
-    if(m_thread) m_thread->join();
+    if ( m_thread ) m_thread->join( );
 
   }
   m_thread = nullptr;
diff --git a/sumrice/Utils.h b/sumrice/Utils.h
index 5c32131ba708818b44f2be25e71e681b456e14dc..d7e811f9fada1d2dbc9d9d9c65334a3118192a2f 100644
--- a/sumrice/Utils.h
+++ b/sumrice/Utils.h
@@ -13,133 +13,175 @@
 #include <thread>
 
 #ifdef VISIMPL_USE_ZEROEQ
+
 #include <zeroeq/zeroeq.h>
+
 #endif
 
+#include <scoop/Color.h>
+#include <QColor>
+
 namespace visimpl
 {
-  bool isValidIPAddress(const std::string &address);
+  bool isValidIPAddress( const std::string& address );
+
+  std::pair< QColor , QColor > generateColorPair( const scoop::Color& color );
+
+  template< class ForwardIt , class T , class Compare >
+  ForwardIt lower_bound( ForwardIt first , ForwardIt last ,
+                         const T& value , Compare comp )
+  {
+    ForwardIt it;
+    typename std::iterator_traits< ForwardIt >::difference_type count , step;
+    count = std::distance( first , last );
+
+    while ( count > 0 )
+    {
+      it = first;
+      step = count / 2;
+      std::advance( it , step );
+      if ( comp( *it , value ))
+      {
+        first = ++it;
+        count -= step + 1;
+      }
+      else
+        count = step;
+    }
+    return first;
+  }
 
 #ifdef VISIMPL_USE_ZEROEQ
+
   class ZeroEQConfig
   {
-    public:
-      /** \brief Singleton instance method.
-       *
-       */
-      static ZeroEQConfig &instance();
-
-      /** \brief ZeroEQConfig session constructor.
-       * \param[in] s Session id.
-       *
-       */
-      void connect(const std::string &s = std::string());
-
-      /** \brief ZeroEQConfig null session constructor.
-       * \param[in] h Host address.
-       * \param[in] p Address port.
-       * \param[in] invert false to use port for subscriber, true to use it with publisher.
-       *
-       */
-      void connect(const std::string &h, const uint16_t p, bool invert = false);
-
-      /** \brief Uses a publisher in the range of known ports and subscribes to all except used publisher.
-       *
-       */
-      void connectNullSession();
-
-      /** \brief Prints the current configuration.
-       *
-       */
-      void print() const;
-
-      /** \brief Returns the publisher connection port or 0 if not connected.
-       *
-       */
-      uint16_t port() const
-      { return m_port; }
-
-      /** \brief Returns the publisher host or empty if not connected.
-       *
-       */
-      const std::string &host() const
-      { return m_host; }
-
-      /** \brief Returns the session id or empty if not connected.
-       *
-       */
-      const std::string &session() const
-      { return m_session; }
-
-      /** \brief Returns the ZeroEQ subscriber or nullptr if not connected.
-       *
-       */
-      std::shared_ptr<zeroeq::Subscriber> subscriber() const
-      { return m_subscriber; }
-
-      /** \brief Returns the ZeroEQ publisher or nullptr if not connected.
-       *
-       */
-      std::shared_ptr<zeroeq::Publisher> publisher() const
-      { return m_publisher; }
-
-      /** \brief Returns true if connected and false otherwise.
-       *
-       */
-      bool isConnected() const
-      { return (m_subscriber != nullptr) && (m_publisher != nullptr); };
-
-      /** \brief Disconnects from ZeroEQ if connected and clears the variables.
-       *
-       */
-      void disconnect();
-
-      /** \brief Starts the event receive loop.
-       *
-       */
-      void startReceiveLoop();
-
-      /** \brief Stops the event receive loop.
-       *
-       */
-      void stopReceiveLoop();
-
-      /** \brief Returns if the receiving loop is running.
-       *
-       */
-      bool isListening() const
-      { return m_run; }
-
-      ZeroEQConfig(ZeroEQConfig const&)   = delete;
-      void operator=(ZeroEQConfig const&) = delete;
-
-    private:
-      /** \brief Ports used for null session without parameters, the first free will be used
-       * for publisher and the rest will be subscribed.
-       *
-       */
-      std::vector<uint16_t> PORTS{50000,51000,52000,53000,54000};
-
-      /** \brief ZeroEQConfig empty class constructor.
-       *
-       */
-      ZeroEQConfig()
-      : m_host{}, m_port{0}, m_session(zeroeq::DEFAULT_SESSION), m_subscriber{nullptr}, m_publisher{nullptr}, m_thread{nullptr}, m_run{false} {};
-
-      /** \brief ZeroEQConfig destructor.
-       *
-       */
-      ~ZeroEQConfig();
-
-    private:
-      std::string                         m_host;       /** null session host address.               */
-      uint16_t                            m_port;       /** null session adddres port.               */
-      std::string                         m_session;    /** session id.                              */
-      std::shared_ptr<zeroeq::Subscriber> m_subscriber; /** ZeroEQ subscriber.                       */
-      std::shared_ptr<zeroeq::Publisher>  m_publisher;  /** ZeroEQ publisher.                        */
-      std::shared_ptr<std::thread>        m_thread;     /** receive loop thread. std::make_unique... */
-      bool                                m_run;        /** true if thread running, false to stop.   */
+  public:
+    /** \brief Singleton instance method.
+     *
+     */
+    static ZeroEQConfig& instance( );
+
+    /** \brief ZeroEQConfig session constructor.
+     * \param[in] s Session id.
+     *
+     */
+    void connect( const std::string& s = std::string( ));
+
+    /** \brief ZeroEQConfig null session constructor.
+     * \param[in] h Host address.
+     * \param[in] p Address port.
+     * \param[in] invert false to use port for subscriber, true to use it with publisher.
+     *
+     */
+    void
+    connect( const std::string& h , const uint16_t p , bool invert = false );
+
+    /** \brief Uses a publisher in the range of known ports and subscribes to all except used publisher.
+     *
+     */
+    void connectNullSession( );
+
+    /** \brief Prints the current configuration.
+     *
+     */
+    void print( ) const;
+
+    /** \brief Returns the publisher connection port or 0 if not connected.
+     *
+     */
+    uint16_t port( ) const
+    { return m_port; }
+
+    /** \brief Returns the publisher host or empty if not connected.
+     *
+     */
+    const std::string& host( ) const
+    { return m_host; }
+
+    /** \brief Returns the session id or empty if not connected.
+     *
+     */
+    const std::string& session( ) const
+    { return m_session; }
+
+    /** \brief Returns the ZeroEQ subscriber or nullptr if not connected.
+     *
+     */
+    std::shared_ptr< zeroeq::Subscriber > subscriber( ) const
+    { return m_subscriber; }
+
+    /** \brief Returns the ZeroEQ publisher or nullptr if not connected.
+     *
+     */
+    std::shared_ptr< zeroeq::Publisher > publisher( ) const
+    { return m_publisher; }
+
+    /** \brief Returns true if connected and false otherwise.
+     *
+     */
+    bool isConnected( ) const
+    { return ( m_subscriber != nullptr ) && ( m_publisher != nullptr ); };
+
+    /** \brief Disconnects from ZeroEQ if connected and clears the variables.
+     *
+     */
+    void disconnect( );
+
+    /** \brief Starts the event receive loop.
+     *
+     */
+    void startReceiveLoop( );
+
+    /** \brief Stops the event receive loop.
+     *
+     */
+    void stopReceiveLoop( );
+
+    /** \brief Returns if the receiving loop is running.
+     *
+     */
+    bool isListening( ) const
+    { return m_run; }
+
+    ZeroEQConfig( ZeroEQConfig const& ) = delete;
+
+    void operator=( ZeroEQConfig const& ) = delete;
+
+  private:
+    /** \brief Ports used for null session without parameters, the first free will be used
+     * for publisher and the rest will be subscribed.
+     *
+     */
+    std::vector< uint16_t > PORTS{ 50000 , 51000 , 52000 , 53000 , 54000 };
+
+    /** \brief ZeroEQConfig empty class constructor.
+     *
+     */
+    ZeroEQConfig( )
+      : m_host{ }
+      , m_port{ 0 }
+      , m_session( zeroeq::DEFAULT_SESSION )
+      , m_subscriber{ nullptr }
+      , m_publisher{ nullptr }
+      , m_thread{ nullptr }
+      , m_run{ false }
+    { };
+
+    /** \brief ZeroEQConfig destructor.
+     *
+     */
+    ~ZeroEQConfig( );
+
+  private:
+    std::string m_host;       /** null session host address.               */
+    uint16_t m_port;       /** null session adddres port.               */
+    std::string m_session;    /** session id.                              */
+    std::shared_ptr< zeroeq::Subscriber > m_subscriber; /** ZeroEQ subscriber.                       */
+    std::shared_ptr< zeroeq::Publisher > m_publisher;  /** ZeroEQ publisher.                        */
+    std::shared_ptr< std::thread > m_thread;     /** receive loop thread. std::make_unique... */
+    bool m_run;        /** true if thread running, false to stop.   */
   };
+
 #endif
 }
 
diff --git a/sumrice/types.h b/sumrice/types.h
index 11b2ec10316f0bd30e36fd66617a91836ec17069..77ecfc1c3be2444d99af4ec88f1a24dd1b631bca 100644
--- a/sumrice/types.h
+++ b/sumrice/types.h
@@ -32,11 +32,13 @@
 #include <QColor>
 #include <QPainterPath>
 
-#include <prefr/prefr.h>
 #include <vmmlib/vmmlib.h>
 
 #include <simil/simil.h>
 
+#include <glm/vec3.hpp>
+#include <glm/vec4.hpp>
+
 namespace visimpl
 {
   typedef simil::Event Event;
@@ -56,7 +58,6 @@ namespace visimpl
   typedef std::vector< vmml::Vector3f > TPosVect;
 
   typedef std::unordered_set< uint32_t > GIDUSet;
-  typedef utils::InterpolationSet< glm::vec4 > TColorMapper;
 
   typedef std::pair< float, QColor > TTFColor;
   typedef std::vector< TTFColor > TTransferFunction;
@@ -67,6 +68,8 @@ namespace visimpl
   typedef glm::vec3 vec3;
   typedef glm::vec4 vec4;
 
+  typedef std::vector< std::pair< float, glm::vec4 >> TColorVec;
+
   typedef enum
   {
     T_STACK_FIXED = 0,
diff --git a/visimpl/CMakeLists.txt b/visimpl/CMakeLists.txt
index b2eda70ad87eaaf79ddc52193a101e4d0e634069..12dc1ff4061aa4076ae6400c8fbe3a7e62594d3d 100644
--- a/visimpl/CMakeLists.txt
+++ b/visimpl/CMakeLists.txt
@@ -5,10 +5,10 @@
 #
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
-add_definitions(-DVISIMPL_SKIP_GLEW_INCLUDE )
-
 set(PROJECT_VERSION_ABI ${${PROJECT_NAME}_VERSION_ABI})
 
+add_definitions(-DVISIMPL_SKIP_GLEW_INCLUDE -DPLAB_SKIP_GLEW_INCLUDE)
+
 set(Name Visimpl)
 set(NAME VISIMPL)
 set(namespace visimpl)
@@ -30,10 +30,11 @@ set(QRCDIR ${PROJECT_SOURCE_DIR}/qrc)
 set(VISIMPL_SOURCES
   ${PROJECT_BINARY_DIR}/src/visimpl/version.cpp
 
+  visimpl.cpp
+
   visimpl.ui
   resources.qrc
 
-  visimpl.cpp
   MainWindow.cpp
   OpenGLWidget.cpp
 
@@ -43,10 +44,10 @@ set(VISIMPL_SOURCES
   SelectionManagerWidget.cpp
   SubsetImporter.cpp
 
-  prefr/ColorSource.cpp
-  prefr/ColorOperationModel.cpp
-  prefr/SourceMultiPosition.cpp
-  prefr/UpdaterStaticPosition.cpp
+  GlewInitializer.cpp
+
+  particlelab/NeuronParticle.cpp
+  particlelab/StaticGradientModel.cpp
 
   render/Plane.cpp
 )
@@ -62,11 +63,12 @@ set(VISIMPL_HEADERS
   SelectionManagerWidget.h
   SubsetImporter.h
 
-  prefr/PrefrShaders.h
-  prefr/ColorSource.h
-  prefr/ColorOperationModel.h
-  prefr/SourceMultiPosition.h
-  prefr/UpdaterStaticPosition.h
+  GlewInitializer.h
+
+  particlelab/ParticleLabShaders.h
+  particlelab/NeuronParticle.h
+  particlelab/StaticGradientModel.h
+
   render/Plane.h
 )
 
@@ -78,7 +80,7 @@ set(VISIMPL_LINK_LIBRARIES
   Qt5::OpenGL
   ReTo
   SimIL
-  prefr
+  plab
   sumrice
   scoop
   acuterecorder
diff --git a/visimpl/DomainManager.cpp b/visimpl/DomainManager.cpp
index 11bcb5c393eca91379e8da5491f1b5efec55bc93..27ae227d9ca998413d6f30d03aa52b7ec368e185 100644
--- a/visimpl/DomainManager.cpp
+++ b/visimpl/DomainManager.cpp
@@ -1,1338 +1,594 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-// ViSimpl
+//
+// Created by gaeqs on 21/06/22.
+//
+
 #include "DomainManager.h"
-#include "VisualGroup.h"
+#include "visimpl/particlelab/ParticleLabShaders.h"
 
-// Prefr
-#include "prefr/UpdaterStaticPosition.h"
-#include "prefr/SourceMultiPosition.h"
+#include <utility>
 
-// C++
-#include <exception>
 
 namespace visimpl
 {
-  void expandBoundingBox( glm::vec3& minBounds,
-                          glm::vec3& maxBounds,
-                          const glm::vec3& position)
-  {
-    for(const auto i: {0,1,2})
-    {
-      minBounds[ i ] = std::min( minBounds[ i ], position[ i ] );
-      maxBounds[ i ] = std::max( maxBounds[ i ], position[ i ] );
-    }
-  }
 
-  constexpr float invRGBInt = 1.0f / 255;
-
-  static std::unordered_map< std::string, std::string > _attributeNameLabels =
-  {
-    {"PYR", "Pyramidal"}, {"INT", "Interneuron"},
-    {"EXC", "Excitatory"}, {"INH", "Inhibitory"}
-  };
-
-
-  DomainManager::DomainManager( prefr::ParticleSystem* particleSystem,
-                                      const TGIDSet& gids)
-  : _particleSystem( particleSystem )
-  , _gids( gids )
-  , _clusterSelected( nullptr )
-  , _clusterUnselected( nullptr )
-  , _clusterHighlighted( nullptr )
-  , _sourceSelected( nullptr )
-  , _currentAttrib( T_TYPE_UNDEFINED )
-  , _modelBase( nullptr )
-  , _modelOff( nullptr )
-  , _modelHighlighted( nullptr )
-  , _sampler( nullptr )
-  , _updater( nullptr )
-  , _mode( TMODE_SELECTION )
-  , _decayValue( 0.0f )
-  , _showInactive( true )
-  , _groupByName( false )
-  , _autoGroupByName( true )
-  {
-  }
-
-  void DomainManager::init( const tGidPosMap& positions
-#ifdef SIMIL_USE_BRION
-                            , const brion::BlueConfig* blueConfig
-#endif
-  )
+  DomainManager::DomainManager( )
+    : _mode( VisualMode::Selection )
+    , _camera( nullptr )
+    , _selectionGids( )
+    , _selectionCluster( nullptr )
+    , _groupClusters( )
+    , _attributeClusters( )
+    , _attributeNames( )
+    , _attributeTypeGids( )
+    , _selectionModel( nullptr )
+    , _currentRenderer( nullptr )
+    , _defaultRenderer( nullptr )
+    , _solidRenderer( nullptr )
+    , _decay( 0.0f )
   {
-    _gidPositions = positions;
-
-#ifdef SIMIL_USE_BRION
-    if( blueConfig )
-      _gidTypes = _loadNeuronTypes( *blueConfig );
-#endif
-
-    _sourceSelected = new SourceMultiPosition( );
-
-    _sourceSelected->setPositions( _gidPositions );
-
-    _clusterSelected = new prefr::Cluster( );
-    _clusterUnselected = new prefr::Cluster( );
-    _clusterHighlighted = new prefr::Cluster( );
-
-    _particleSystem->addCluster( _clusterSelected );
-    _particleSystem->addCluster( _clusterUnselected );
-    _particleSystem->addCluster( _clusterHighlighted );
-
-    _loadPaletteColors( );
   }
 
-  void DomainManager::initializeParticleSystem( prefr::IGLRenderProgram* program )
+  void DomainManager::initRenderers(
+    const std::shared_ptr< reto::ClippingPlane >& leftPlane ,
+    const std::shared_ptr< reto::ClippingPlane >& rightPlane ,
+    const std::shared_ptr< plab::ICamera >& camera )
   {
-    std::cout << "Initializing particle system..." << std::endl;
-
-    _updater = new UpdaterStaticPosition( );
-
-    prefr::Sorter* sorter = new prefr::Sorter( );
-    prefr::OIGLRenderer* renderer = new prefr::OIGLRenderer( program );
-
-    _particleSystem->addUpdater( _updater );
-    _particleSystem->sorter( sorter );
-    _particleSystem->renderer( renderer );
-
-    _modelOff = new prefr::ColorOperationModel( _decayValue, _decayValue );
-    _modelOff->color.Insert( 0.0f, ( glm::vec4(0.1f, 0.1f, 0.1f, 0.2f)));
+    _camera = camera;
 
-    _modelOff->velocity.Insert( 0.0f, 0.0f );
+    _selectionCluster =
+      std::make_shared< plab::Cluster< NeuronParticle >>( );
 
-    _modelOff->size.Insert( 1.0f, 10.0f );
+    TColorVec colors;
+    colors.emplace_back( 0.0f , glm::vec4( 0.0f , 1.0f , 0.0f , 0.2f ));
+    colors.emplace_back( 0.35f , glm::vec4( 1.0f , 0.0f , 0.0f , 0.5f ));
+    colors.emplace_back( 0.7f , glm::vec4( 1.0f , 1.0f , 0.0f , 0.5f ));
+    colors.emplace_back( 1.0f , glm::vec4( 0.0f , 0.0f , 1.0f , 0.5f ));
 
-    _particleSystem->addModel( _modelOff );
+    TSizeFunction sizes;
+    sizes.emplace_back( 0.0f , 8.0f );
+    sizes.emplace_back( 1.0f , 6.0f );
 
-    _modelHighlighted = new prefr::ColorOperationModel( _decayValue, _decayValue );
-    _modelHighlighted->color.Insert( 0.0f, ( glm::vec4( 0.9f, 0.9f, 0.9f, 0.5f )));
-    _modelHighlighted->color.Insert( 1.0f, ( glm::vec4( 0.75f, 0.75f, 0.75f, 0.2f )));
-    _modelHighlighted->velocity.Insert( 0.0f, 0.0f );
-    _modelHighlighted->size.Insert( 0.0f, 20.0f );
-    _modelHighlighted->size.Insert( 1.0f, 10.0f );
-    _particleSystem->addModel( _modelHighlighted );
+    _selectionModel = std::make_shared< StaticGradientModel >(
+      camera , leftPlane , rightPlane , sizes , colors ,
+      true , false , 0.0f );
 
+    _defaultProgram.loadFromText(
+      visimpl::PARTICLE_VERTEX_SHADER ,
+      visimpl::PARTICLE_DEFAULT_FRAGMENT_SHADER );
+    _defaultProgram.compileAndLink( );
 
-    _modelBase = new prefr::ColorOperationModel( _decayValue, _decayValue );
-    _modelBase->color.Insert( 0.0f, ( glm::vec4(0.f, 1.f, 0.f, 0.2)));
-    _modelBase->color.Insert( 0.35f, ( glm::vec4(1, 0, 0, 0.5 )));
-    _modelBase->color.Insert( 0.7f, ( glm::vec4(1.f, 1.f, 0, 0.5 )));
-    _modelBase->color.Insert( 1.0f, ( glm::vec4(0, 0, 1.f, 0.5 )));
+    _solidProgram.loadFromText(
+      visimpl::PARTICLE_VERTEX_SHADER ,
+      visimpl::PARTICLE_SOLID_FRAGMENT_SHADER );
+    _solidProgram.compileAndLink( );
 
-    _modelBase->velocity.Insert( 0.0f, 0.0f );
+    _defaultRenderer = std::make_shared< plab::CoverageRenderer >(
+      _defaultProgram.program( ));
+    _solidRenderer = std::make_shared< plab::CoverageRenderer >(
+      _solidProgram.program( ));
 
-    _modelBase->size.Insert( 0.0f, 20.0f );
-    _modelBase->size.Insert( 1.0f, 10.0f );
+    _currentRenderer = _defaultRenderer;
 
-    _particleSystem->addModel( _modelBase );
-
-    _sampler = new prefr::PointSampler( );
-
-    _particleSystem->renderDeadParticles( true );
-    _particleSystem->parallel( true );
-
-    _particleSystem->start();
+    _selectionCluster->setModel( _selectionModel );
+    _selectionCluster->setRenderer( _currentRenderer );
   }
 
-  const tGidPosMap& DomainManager::positions( void ) const
-  {
-    return _gidPositions;
-  }
+#ifdef SIMIL_USE_BRION
 
-  void DomainManager::reloadPositions( void )
+  void DomainManager::initAttributeData(
+    const TGIDSet& gids ,
+    const brion::BlueConfig* blueConfig )
   {
-    if(_gidToParticle.empty()) return;
+    if ( blueConfig == nullptr ) return;
+    brion::Circuit circuit( blueConfig->getCircuitSource( ));
+    uint32_t attributes = brion::NEURON_COLUMN_GID |
+                          brion::NEURON_MTYPE |
+                          brion::NEURON_ETYPE;
+    const auto& attributeData = circuit.get( gids , attributes );
 
-    _resetBoundingBox( );
+    auto rawMorphoNames = circuit.getTypes(
+      brion::NEURONCLASS_MORPHOLOGY_CLASS );
+    auto rawFuncNames = circuit.getTypes(
+      brion::NEURONCLASS_FUNCTION_CLASS );
 
-    auto expandBB = [this](const std::pair<unsigned int, unsigned int> &gidPartId)
-    {
-      const auto pos = _gidPositions.find( gidPartId.first );
+    _attributeNames[ T_TYPE_MORPHO ] = rawMorphoNames;
+    _attributeNames[ T_TYPE_FUNCTION ] = rawFuncNames;
+    auto& morphoNames = _attributeNames[ T_TYPE_MORPHO ];
+    auto& funcNames = _attributeNames[ T_TYPE_FUNCTION ];
+    std::sort( morphoNames.begin( ) , morphoNames.end( ));
+    std::sort( funcNames.begin( ) , funcNames.end( ));
 
-      auto particle = _particleSystem->particles( ).at( gidPartId.second );
-      particle.set_position( pos->second );
+    morphoNames.erase( std::unique( morphoNames.begin( ) , morphoNames.end( )) ,
+                       morphoNames.end( ));
+    funcNames.erase( std::unique( funcNames.begin( ) , funcNames.end( )) ,
+                     funcNames.end( ));
 
-      expandBoundingBox( _boundingBox.first,
-                         _boundingBox.second,
-                         pos->second );
-    };
-    std::for_each(_gidToParticle.cbegin(), _gidToParticle.cend(), expandBB);
-  }
-
-  const TGIDSet& DomainManager::gids( void ) const
-  {
-    return _gids;
-  }
-
-  void DomainManager::mode(const tVisualMode newMode )
-  {
-    clearView( );
+    _attributeTypeGids[ T_TYPE_MORPHO ] =
+      std::vector< std::vector< uint32_t > >( morphoNames.size( ));
+    _attributeTypeGids[ T_TYPE_FUNCTION ] =
+      std::vector< std::vector< uint32_t > >( funcNames.size( ));
+    auto& morphoSets = _attributeTypeGids[ T_TYPE_MORPHO ];
+    auto& funcSets = _attributeTypeGids[ T_TYPE_FUNCTION ];
 
-    _mode = newMode;
 
-    switch( _mode )
+    uint32_t i = 0;
+    for ( const auto& gid: gids )
     {
-      case TMODE_SELECTION:
-        _generateSelectionIndices( );
-        break;
-      case TMODE_GROUPS:
-        _generateGroupsIndices( );
-        break;
-      case TMODE_ATTRIBUTE:
-        generateAttributesGroups( _currentAttrib == T_TYPE_UNDEFINED ?
-                                  T_TYPE_MORPHO : _currentAttrib );
+      auto morphoType = boost::lexical_cast< unsigned int >(
+        attributeData[ i ][ 1 ] );
+      auto functionType = boost::lexical_cast< unsigned int >(
+        attributeData[ i ][ 2 ] );
 
-        _generateAttributesIndices( );
-        break;
-      default:
-        {
-          const auto message = std::string("Invalid tVisualMode value ") +
-                               std::to_string(static_cast<int>(newMode)) + " " +
-                               std::string(__FILE__) + ":" +
-                               std::to_string(__LINE__);
-          throw std::out_of_range(message.c_str());
-        }
-        break;
-    }
-  }
+      auto& morphoName = rawMorphoNames[ morphoType ];
+      auto& funcName = rawFuncNames[ functionType ];
 
-  tVisualMode DomainManager::mode( void ) const
-  {
-    return _mode;
-  }
+      int morphoIndex = std::distance(
+        morphoNames.begin( ) ,
+        std::find( morphoNames.begin( ) , morphoNames.end( ) , morphoName ));
 
-  void DomainManager::clearView( void )
-  {
-    switch( _mode )
-    {
-      case TMODE_SELECTION:
-        _clearSelectionView( );
-        break;
-      case TMODE_GROUPS:
-        _clearGroupsView( );
-        break;
-      case TMODE_ATTRIBUTE:
-        _clearAttribView( );
-        break;
-      default:
-        {
-          const auto message = std::string("Invalid tVisualMode value ") +
-                               std::to_string(static_cast<int>(_mode)) + " " +
-                               std::string(__FILE__) + ":" +
-                               std::to_string(__LINE__);
-          throw std::out_of_range(message.c_str());
-        }
-        break;
-    }
-  }
+      int funcIndex = std::distance(
+        funcNames.begin( ) ,
+        std::find( funcNames.begin( ) , funcNames.end( ) , funcName ));
 
-  void DomainManager::_clearParticlesReference( void )
-  {
-    _gidToParticle.clear( );
-    _particleToGID.clear( );
 
-    _gidSource.clear( );
-  }
+      morphoSets[ morphoIndex ].push_back( gid );
+      funcSets[ funcIndex ].push_back( gid );
 
-  void DomainManager::_clearSelectionView( void )
-  {
-    if(_sourceSelected )
-      _particleSystem->detachSource( _sourceSelected );
-
-    _clearParticlesReference( );
-  }
-
-  void DomainManager::_clearGroupsView( void )
-  {
-    for( auto group : _groups )
-    {
-      _clearGroup( group, false );
+      i++;
     }
-
-    _clearParticlesReference( );
   }
 
-  void DomainManager::_clearAttribView( void )
-  {
-    for( auto group : _attributeGroups )
-    {
-      _clearGroup( group, false );
-    }
-
-    _clearParticlesReference( );
-  }
+#endif
 
-  void DomainManager::_clearGroups( void )
+  std::shared_ptr< plab::Cluster< NeuronParticle >>
+  DomainManager::getSelectionCluster( ) const
   {
-    for( auto group : _groups )
-      delete group;
-
-    _groups.clear( );
+    return _selectionCluster;
   }
 
-  void DomainManager::_clearAttribs( bool clearCustom )
+  const std::shared_ptr< StaticGradientModel >&
+  DomainManager::getSelectionModel( ) const
   {
-    if( clearCustom )
-    {
-      for( auto group : _attributeGroups )
-        delete group;
-
-      _attributeGroups.clear( );
-    }
-    else
-    {
-      std::vector< VisualGroup* > aux;
-      aux.reserve( _attributeGroups.size( ));
-      for( auto group : _attributeGroups )
-        if( group->custom( ))
-          aux.push_back( group );
-        else
-          delete group;
-      aux.shrink_to_fit( );
-      _attributeGroups = aux;
-    }
+    return _selectionModel;
   }
 
-  void DomainManager::_loadPaletteColors( void )
+  int DomainManager::getGroupAmount( ) const
   {
-    scoop::ColorPalette palette =
-        scoop::ColorPalette::colorBrewerQualitative(
-            ( scoop::ColorPalette::ColorBrewerQualitative::Set1 ), 9 );
-
-    auto colors = palette.colors( );
-
-    _paletteColors.clear( );
-
-    for( auto color: colors )
-    {
-      _paletteColors.emplace_back( generateColorPair(color) );
-    }
+    return _groupClusters.size( );
   }
 
-  void DomainManager::update( void )
+  const std::map< std::string , std::shared_ptr< VisualGroup>>&
+  DomainManager::getGroups( ) const
   {
-    switch( _mode )
-    {
-      case TMODE_SELECTION:
-        _generateSelectionIndices( );
-        break;
-      case TMODE_GROUPS:
-        _generateGroupsIndices( );
-        break;
-      case TMODE_ATTRIBUTE:
-        _generateAttributesIndices( );
-        break;
-      default:
-        {
-          const auto message = std::string("Invalid tVisualMode value ") +
-                               std::to_string(static_cast<int>(_mode)) + " " +
-                               std::string(__FILE__) + ":" +
-                               std::to_string(__LINE__);
-          throw std::out_of_range(message.c_str());
-        }
-        break;
-    }
+    return _groupClusters;
   }
 
-  void DomainManager::updateData(const TGIDSet& gids,
-                                 const tGidPosMap& positions)
+  std::shared_ptr< VisualGroup >
+  DomainManager::getGroup( const std::string& name ) const
   {
-    _gids = gids;
-    _gidPositions = positions;
-
-    _sourceSelected->setPositions( _gidPositions );
-    clearView();
-    update();
-    reloadPositions();
+    return _groupClusters.at( name );
   }
 
-  void DomainManager::_resetBoundingBox( void )
+  const std::map< std::string , std::shared_ptr< VisualGroup>>&
+  DomainManager::getAttributeClusters( ) const
   {
-    _boundingBox.first = glm::vec3( std::numeric_limits< float >::max( ),
-                                    std::numeric_limits< float >::max( ),
-                                    std::numeric_limits< float >::max( ));
-
-    _boundingBox.second = glm::vec3( std::numeric_limits< float >::min( ),
-                                     std::numeric_limits< float >::min( ),
-                                     std::numeric_limits< float >::min( ));
+    return _attributeClusters;
   }
 
-  bool DomainManager::showGroups( void )
+  VisualMode DomainManager::getMode( ) const
   {
-    return _mode == TMODE_GROUPS;
+    return _mode;
   }
 
-  void DomainManager::updateGroups( void )
+  void DomainManager::setMode( VisualMode mode )
   {
-    _generateGroupsIndices( );
+    _mode = mode;
   }
 
-  void DomainManager::updateAttributes( void )
+  float DomainManager::getDecay( ) const
   {
-    _generateAttributesIndices( );
+    return _decay;
   }
 
-  void DomainManager::showInactive( bool state )
+  void DomainManager::setDecay( float decay )
   {
-    _showInactive = state;
+    _decay = decay;
   }
 
-  void DomainManager::setVisualGroupState( unsigned int i, bool state, bool attrib )
+  void DomainManager::setTime( float time )
   {
-    VisualGroup* group = nullptr;
-
-    if( !attrib )
+    if ( _selectionModel != nullptr )
     {
-      if( i < _groups.size( ))
-        group = _groups[ i ];
+      _selectionModel->setTime( time );
     }
-    else
-    {
-      if( i < _attributeGroups.size( ))
-        group = _attributeGroups[ i ];
-    }
-
-    if(!group) return;
-
-    group->active( state );
-    group->cluster( )->setModel( state ? group->model( ) : _modelOff );
-
-    if( !_showInactive )
-      group->source( )->active( state );
+    for ( const auto& item: _groupClusters )
+      item.second->getModel( )->setTime( time );
   }
 
-  void DomainManager::_updateGroupsModels( void )
+  void DomainManager::addTime( float time , float endTime )
   {
-    for( auto group : _groups )
+    if ( _selectionModel != nullptr )
     {
-      group->model( group->active( ) ? group->model( ) : _modelOff );
+      _selectionModel->addTime( time , endTime );
     }
+    for ( const auto& item: _groupClusters )
+      item.second->getModel( )->addTime( time , endTime );
   }
 
-  void DomainManager::_updateSelectionIndices( void )
+  const tBoundingBox& DomainManager::getBoundingBox( ) const
   {
-    prefr::ParticleIndices selection;
-    prefr::ParticleIndices other;
-    for( auto gid : _gids )
-    {
-      auto particleId = _gidToParticle.find( gid )->second;
-
-      if( _selection.empty( ) || _selection.find( gid ) != _selection.end( ))
-        selection.push_back( particleId );
-      else
-        other.push_back( particleId );
-    }
-    _clusterSelected->particles( ).indices( selection );
-    _clusterUnselected->particles( ).indices( other );
-
-    _clusterSelected->setModel( _modelBase );
-    _clusterUnselected->setModel( _modelOff );
+    return _boundingBox;
   }
 
-  void DomainManager::_generateSelectionIndices( void )
+  void DomainManager::setSelection( const TGIDSet& gids ,
+                                    const tGidPosMap& positions )
   {
-    unsigned int numParticles = _gids.size( );
-
-    prefr::ParticleIndices indices;
-    prefr::ParticleIndices indicesSelected;
-    prefr::ParticleIndices indicesUnselected;
+    _selectionGids.clear( );
+    std::copy(
+      gids.cbegin( ) , gids.cend( ) ,
+      std::back_inserter( _selectionGids )
+    );
 
-    indices.reserve( numParticles );
-    indicesSelected.reserve( numParticles );
-    indicesUnselected.reserve( numParticles );
+    float minLimit = std::numeric_limits< float >::min( );
+    float maxLimit = std::numeric_limits< float >::max( );
+    glm::vec3 min( maxLimit , maxLimit , maxLimit );
+    glm::vec3 max( minLimit , minLimit , minLimit );
 
-    auto availableParticles =  _particleSystem->retrieveUnused( numParticles );
-    const auto count = availableParticles.size();
-    _gidToParticle.reserve(count);
-    _particleToGID.reserve(count);
-    _gidSource.reserve(count);
-
-    _resetBoundingBox( );
-
-    auto gidit = _gids.begin( );
-    for( auto particle : availableParticles )
+    std::vector< NeuronParticle > particles;
+    for ( const auto& gid: _selectionGids )
     {
-      const unsigned int id = particle.id( );
-
-      // Create reference
-      _gidToParticle.insert( std::make_pair( *gidit, id ));
-      _particleToGID.insert( std::make_pair( id, *gidit ));
+      NeuronParticle p;
+      p.position = positions.at( gid );
+      particles.push_back( p );
 
-      _gidSource.insert( std::make_pair( *gidit, _sourceSelected ));
-
-      // Check if part of selection
-      if( _selection.empty( ) || _selection.find( *gidit ) != _selection.end( ))
-      {
-        indicesSelected.emplace_back( id );
-
-        const auto pos = _gidPositions.find( *gidit )->second;
-        expandBoundingBox( _boundingBox.first, _boundingBox.second, pos );
-      }
-      else
-      {
-        indicesUnselected.emplace_back( id );
-      }
-
-      indices.emplace_back( id );
-
-      ++gidit;
+      min = glm::min( min , p.position );
+      max = glm::max( max , p.position );
     }
 
-    indicesSelected.shrink_to_fit( );
-    indicesUnselected.shrink_to_fit( );
-
-    _clusterSelected->particles( ).indices( indicesSelected );
-    _clusterUnselected->particles( ).indices( indicesUnselected );
-
-    _sourceSelected->setIdxTranslation( _particleToGID );
-
-    _particleSystem->addSource( _sourceSelected, indices );
-
-    _clusterSelected->setUpdater( _updater );
-    _clusterUnselected->setUpdater( _updater );
+    _boundingBox = std::make_pair( min , max );
 
-    _clusterUnselected->setModel( _modelOff );
-    _clusterSelected->setModel( _modelBase );
+    _selectionCluster->setParticles( particles );
   }
 
-  VisualGroup* DomainManager::_generateGroup( const GIDUSet& gids,
-                                              const std::string& name,
-                                              unsigned int idx ) const
+  void DomainManager::setSelection( const GIDUSet& gids ,
+                                    const tGidPosMap& positions )
   {
-    VisualGroup* group = new VisualGroup( name );
+    _selectionGids.clear( );
+    std::copy(
+      gids.cbegin( ) , gids.cend( ) ,
+      std::back_inserter( _selectionGids )
+    );
 
-    // Create model from base
-    prefr::ColorOperationModel* model =
-        new prefr::ColorOperationModel( *_modelBase );
-    group->model( model );
+    float minLimit = std::numeric_limits< float >::min( );
+    float maxLimit = std::numeric_limits< float >::max( );
+    glm::vec3 min( maxLimit , maxLimit , maxLimit );
+    glm::vec3 max( minLimit , minLimit , minLimit );
 
-    TTransferFunction colorVariation;
-    auto colors = _paletteColors[ idx % _paletteColors.size( )];
-    colorVariation.push_back( std::make_pair( 0.0f, colors.first ));
-    colorVariation.push_back( std::make_pair( 1.0f, colors.second ));
-    group->colorMapping( colorVariation );
-
-    prefr::Cluster* cluster = new prefr::Cluster( );
-
-    SourceMultiPosition* source = new SourceMultiPosition( );
-    source->setPositions( _gidPositions );
-    source->setIdxTranslation( _particleToGID );
-
-    group->cluster( cluster );
-    group->source( source );
+    std::vector< NeuronParticle > particles;
+    for ( const auto& gid: _selectionGids )
+    {
+      NeuronParticle p;
+      p.position = positions.at( gid );
+      particles.push_back( p );
 
-    group->gids( gids );
+      min = glm::min( min , p.position );
+      max = glm::max( max , p.position );
+    }
 
-    group->active( true );
-    group->cached( false );
-    group->dirty( true );
+    _boundingBox = std::make_pair( min , max );
 
-    return group;
+    _selectionCluster->setParticles( particles );
   }
 
-  VisualGroup* DomainManager::addVisualGroupFromSelection( const std::string& name,
-                                                           bool overrideGIDs )
+  std::shared_ptr< VisualGroup > DomainManager::createGroup(
+    const GIDUSet& gids , const tGidPosMap& positions ,
+    const std::string& name )
   {
-    return addVisualGroup( _selection, name, overrideGIDs );
-  }
+    auto group = std::make_shared< VisualGroup >(
+      name , _camera ,
+      _selectionModel->getLeftPlane( ) ,
+      _selectionModel->getRightPlane( ) ,
+      _currentRenderer ,
+      _selectionModel->isClippingEnabled( ));
 
-  VisualGroup* DomainManager::addVisualGroup( const GIDUSet& gids,
-                                              const std::string& name,
-                                              bool overrideGIDS )
-  {
-    VisualGroup* group = _generateGroup( gids, name, _groups.size( ));
-    group->custom( true );
-
-    if(overrideGIDS)
-    {
-      for( auto gid : gids )
-      {
-        auto reference = _neuronGroup.find( gid );
+    group->getModel( )->setAccumulativeMode(
+      _selectionModel->isAccumulativeMode( ));
 
-        if( reference != _neuronGroup.end( ))
-        {
-          auto& oldGroup = reference->second;
+    std::vector< uint32_t > ids;
+    std::vector< NeuronParticle > particles;
 
-          auto oldGroupGIDs = oldGroup->gids( );
-          oldGroupGIDs.erase( gid );
-          reference->second->gids( oldGroupGIDs );
+    std::copy(
+      gids.cbegin( ) , gids.cend( ) ,
+      std::back_inserter( ids )
+    );
 
-          oldGroup->cached( false );
-        }
-      }
+    for ( const auto& gid: ids )
+    {
+      NeuronParticle p;
+      p.position = positions.at( gid );
+      particles.push_back( p );
     }
-    _groups.push_back( group );
+
+    group->setParticles( ids , particles );
+    _groupClusters[ name ] = group;
 
     return group;
   }
 
-  void DomainManager::removeVisualGroup( unsigned int i )
+  std::shared_ptr< VisualGroup >
+  DomainManager::createGroupFromSelection(
+    const tGidPosMap& positions , const std::string& name )
   {
-    auto group = _groups[ i ];
-
-    _clearGroup( group, true );
-
-    delete group;
-
-    _groups.erase( _groups.begin( ) + i );
-  }
+    auto group = std::make_shared< VisualGroup >(
+      name , _camera ,
+      _selectionModel->getLeftPlane( ) ,
+      _selectionModel->getRightPlane( ) ,
+      _currentRenderer ,
+      _selectionModel->isClippingEnabled( ));
 
-  void DomainManager::_clearGroup( VisualGroup* group, bool clearState )
-  {
-    _particleSystem->detachSource( group->source( ));
+    group->getModel( )->setAccumulativeMode(
+      _selectionModel->isAccumulativeMode( ));
 
-    if( clearState )
+    std::vector< NeuronParticle > particles;
+    for ( const auto& gid: _selectionGids )
     {
-      for( auto gid : group->gids( ))
-      {
-        auto ref = _gidToParticle.find( gid );
-
-        if( ref != _gidToParticle.end( ))
-        {
-        _particleToGID.erase( ref->second );
-        _gidToParticle.erase( ref );
-        }
-        _neuronGroup.erase( gid );
-      }
+      NeuronParticle p;
+      p.position = positions.at( gid );
+      particles.push_back( p );
     }
 
-    group->cached( false );
-    group->dirty( true );
-  }
-
-  void DomainManager::_generateGroupsIndices( void )
-  {
-    for( auto group : _groups )
-    {
-      if( !group->dirty( ) || !group->active())
-        continue;
-
-      if( group->cached( ))
-        _clearGroup( group, true );
-
-      const auto& gids = group->gids( );
-
-      auto availableParticles =  _particleSystem->retrieveUnused( gids.size( ));
-
-      auto cluster = group->cluster( );
-
-      _particleSystem->addCluster( cluster, availableParticles.indices( ));
-      _particleSystem->addSource( group->source( ), availableParticles.indices( ));
-
-      cluster->setUpdater( _updater );
-      cluster->setModel( group->model( ));
-
-      auto partId = availableParticles.begin( );
-      for( auto gid : gids )
-      {
-        _neuronGroup.insert( std::make_pair( gid, group ));
+    group->setParticles( _selectionGids , particles );
+    _groupClusters[ name ] = group;
 
-        _gidToParticle.insert( std::make_pair( gid, partId.id( )));
-        _particleToGID.insert( std::make_pair( partId.id( ), gid ));
-
-        ++partId;
-      }
-
-      group->cached( true );
-      group->dirty( false );
-    }
+    return group;
   }
 
-  void DomainManager::generateAttributesGroups( tNeuronAttributes attrib )
+  void DomainManager::removeGroup( const std::string& name )
   {
-    if( attrib == _currentAttrib || attrib == T_TYPE_UNDEFINED || _mode != TMODE_ATTRIBUTE  )
-      return;
-
-    _clearAttribView( );
-
-    _clearAttribs( );
-
-    _clearParticlesReference( );
-
-    // Clustering
-    // TODO auto-detect attribute type
-    std::unordered_set< unsigned int > differentValues;
-    std::unordered_multimap< unsigned int, unsigned int > valueGids;
-
-    auto functor = ( [&]( const NeuronAttributes& att )
-        { return ( attrib == T_TYPE_MORPHO ) ? ( std::get< T_TYPE_MORPHO >( att )) :
-                                                 std::get< T_TYPE_FUNCTION >( att ); });
-
-    const auto& typeIndices =
-        ( attrib == T_TYPE_MORPHO ) ? _typeToIdxMorpho : _typeToIdxFunction;
-
-    const auto& nameIndices =
-        ( attrib == T_TYPE_MORPHO ) ? _namesIdxMorpho : _namesIdxFunction;
-
-    for( auto attribs : _gidTypes )
+    if(1 != _groupClusters.erase( name ))
     {
-      unsigned int gid = attribs.first;
-      unsigned int value = typeIndices.find( functor( attribs.second ))->second;
-
-      differentValues.insert( value );
-      valueGids.insert( std::make_pair( value, gid ));
+      std::cerr << "DomainManager: Error removing group '" << name
+                << "' - " << __FILE__ << ":" << __LINE__ << std::endl;
     }
-
-    _attributeGroups.resize( nameIndices.size( ));
-
-    // Generate attrib groups
-    for( auto typeIndex : nameIndices )
-    {
-      GIDUSet gids;
-
-      auto elements = valueGids.equal_range( typeIndex.second );
-      for( auto it = elements.first; it != elements.second; ++it )
-        gids.insert( it->second );
-
-      auto group = _generateGroup( gids, typeIndex.first, typeIndex.second );
-      group->custom( false );
-
-      _attributeGroups[ typeIndex.second ] = group;
-    }
-
-    _generateAttributesIndices( );
-
-    _currentAttrib = attrib;
   }
 
-  void DomainManager::_generateAttributesIndices( void )
+  void DomainManager::selectAttribute(
+    const std::vector< QColor >& colors ,
+    const tGidPosMap& positions ,
+    tNeuronAttributes attribute )
   {
-    for( auto group : _attributeGroups )
-    {
-
-      if( !group->dirty( ))
-        continue;
+    _attributeClusters.clear( );
 
-      if( group->cached( ))
-        _clearGroup( group, true );
+    auto& names = _attributeNames[ attribute ];
+    auto& typeGids = _attributeTypeGids[ attribute ];
 
-      const auto& gids = group->gids( );
-
-      auto availableParticles =  _particleSystem->retrieveUnused( gids.size( ));
+    uint32_t i = 0;
+    for ( const auto& name: names )
+    {
+      auto& gids = typeGids[ i ];
 
-      auto cluster = group->cluster( );
+      auto group = std::make_shared< VisualGroup >(
+        name , _camera ,
+        _selectionModel->getLeftPlane( ) ,
+        _selectionModel->getRightPlane( ) ,
+        _currentRenderer ,
+        _selectionModel->isClippingEnabled( ));
+      group->getModel( )->setAccumulativeMode(
+        _selectionModel->isAccumulativeMode( ));
 
-      _particleSystem->addCluster( cluster, availableParticles.indices( ));
-      _particleSystem->addSource( group->source( ), availableParticles.indices( ));
+      const auto currentIndex = i % colors.size( );
+      const auto color = colors[ currentIndex ].toRgb( );
+      const auto variations = generateColorPair( color );
 
-      cluster->setUpdater( _updater );
-      cluster->setModel( group->model( ));
+      TTransferFunction colorVariation;
+      colorVariation.push_back( std::make_pair( 0.0f , variations.first ));
+      colorVariation.push_back( std::make_pair( 1.0f , variations.second ));
+      group->colorMapping( colorVariation );
 
-      auto partId = availableParticles.begin( );
-      for( auto gid : gids )
+      std::vector< NeuronParticle > particles;
+      for ( const auto& gid: gids )
       {
-        _neuronGroup.insert( std::make_pair( gid, group ));
-
-        _gidToParticle.insert( std::make_pair( gid, partId.id( )));
-        _particleToGID.insert( std::make_pair( partId.id( ), gid ));
-
-        ++partId;
+        NeuronParticle p;
+        p.position = positions.at( gid );
+        particles.push_back( p );
       }
 
-      group->cached( true );
-      group->dirty( false );
-    }
-  }
+      group->setParticles( gids , particles );
 
-  void DomainManager::processInput( const simil::SpikesCRange& spikes_,
-                                       float begin, float end, bool clear )
-  {
-    if( clear )
-      resetParticles( );
+      _attributeClusters[ name ] = group;
 
-    switch( _mode )
-    {
-      case TMODE_SELECTION:
-        _processFrameInputSelection( spikes_, begin, end );
-        break;
-      case TMODE_GROUPS:
-        _processFrameInputGroups( spikes_, begin, end );
-        break;
-      case TMODE_ATTRIBUTE:
-        _processFrameInputAttributes( spikes_, begin, end );
-        break;
-      default:
-        {
-          const auto message = std::string("Invalid tVisualMode value ") +
-                               std::to_string(static_cast<int>(_mode)) + " " +
-                               std::string(__FILE__) + ":" +
-                               std::to_string(__LINE__);
-          throw std::out_of_range(message.c_str());
-        }
-        break;
+      i++;
     }
+
   }
 
-  DomainManager::TModifiedNeurons
-  DomainManager::_parseInput( const simil::SpikesCRange& spikes_,
-                                float /*begin*/, float end )
+  void DomainManager::enableAccumulativeMode( bool enabled )
   {
-    TModifiedNeurons result;
-    std::unordered_map< uint32_t, float > inserted;
-
-    for( simil::SpikesCIter spike = spikes_.first; spike != spikes_.second; ++spike )
+    if ( _selectionModel != nullptr )
     {
-      float lifeValue = _decayValue - ( end - spike->first);
-
-      auto it = inserted.find( spike->second );
-      if( it == inserted.end( ))
-      {
-        inserted[ spike->second ] = lifeValue;
-      }
-    }
-
-    result.reserve( inserted.size( ));
-    for( auto spike : inserted )
-    {
-      result.emplace_back( spike.first, spike.second );
+      _selectionModel->setAccumulativeMode( enabled );
     }
-
-    return result;
+    for ( const auto& item: _groupClusters )
+      item.second->getModel( )->setAccumulativeMode( enabled );
   }
 
-  void DomainManager::_processFrameInputSelection( const simil::SpikesCRange& spikes_,
-                                                     float begin, float end )
+  void DomainManager::enableClipping( bool enabled )
   {
-    if( !_particleSystem || !_particleSystem->run( ) || _mode != TMODE_SELECTION )
-      return;
-
-    auto state = _parseInput( spikes_, begin, end );
-
-    for( const auto& neuron : state )
+    if ( _selectionModel != nullptr )
     {
-      auto gid = std::get< 0 >( neuron );
-
-      if( _selection.empty( ) || _selection.find( gid ) != _selection.end( ))
-      {
-        const auto source = _gidSource.find( gid );
-
-        if( source == _gidSource.end( ))
-        {
-          std::cout << "GID " << gid << " source not found." << std::endl;
-          return;
-        }
-
-        const unsigned int partIdx = _gidToParticle.find( gid )->second;
-        auto particle = _particleSystem->particles( ).at( partIdx );
-        particle.set_life( std::get< 1 >( neuron ));
-      }
+      _selectionModel->enableClipping( enabled );
     }
+    for ( const auto& item: _groupClusters )
+      item.second->getModel( )->enableClipping( enabled );
   }
 
-  void DomainManager::_processFrameInputGroups( const simil::SpikesCRange& spikes_,
-                                                  float begin, float end )
+  void DomainManager::draw( ) const
   {
 
-    if( !_particleSystem || !_particleSystem->run( ) || _mode != TMODE_GROUPS )
-      return;
-
-    auto state = _parseInput( spikes_, begin, end );
-
-    for( const auto& neuron : state )
+    switch ( _mode )
     {
-      auto gid = std::get< 0 >( neuron );
-
-      auto visualGroup = _neuronGroup.find( gid );
-
-      if( visualGroup != _neuronGroup.end( ) && visualGroup->second->active( ))
-      {
-        auto partIt = _gidToParticle.find( gid );
-        if( partIt != _gidToParticle.end( ))
+      case VisualMode::Selection:
+        _selectionCluster->render( );
+        break;
+      case VisualMode::Groups:
+        for ( const auto& item: _groupClusters )
         {
-          unsigned int particleIndex = partIt->second;
-
-          auto particle = _particleSystem->particles( ).at( particleIndex );
-          particle.set_life( std::get< 1 >( neuron ) );
+          if ( item.second->active( ))
+          {
+            item.second->getCluster( )->render( );
+          }
         }
-      }
-    }
-  }
-
-  void DomainManager::_processFrameInputAttributes( const simil::SpikesCRange& spikes_,
-                                                  float begin, float end )
-  {
-
-    if( !_particleSystem || !_particleSystem->run( ) || _mode != TMODE_ATTRIBUTE )
-      return;
-
-    auto state = _parseInput( spikes_, begin, end );
-
-    for( const auto& neuron : state )
-    {
-      auto gid = std::get< 0 >( neuron );
-
-      auto visualGroup = _neuronGroup.find( gid );
-
-      if( visualGroup != _neuronGroup.end( ) && visualGroup->second->active( ))
-      {
-        auto partIt = _gidToParticle.find( gid );
-        if( partIt != _gidToParticle.end( ))
+        break;
+      case VisualMode::Attribute:
+        for ( const auto& item: _attributeClusters )
         {
-          unsigned int particleIndex = partIt->second;
-          auto particle = _particleSystem->particles( ).at( particleIndex );
-          particle.set_life( std::get< 1 >( neuron ) );
+          if ( item.second->active( ))
+          {
+            item.second->getCluster( )->render( );
+          }
         }
-      }
-    }
-  }
-
-  void DomainManager::selection( const GIDUSet& newSelection )
-  {
-    _selection = newSelection;
-
-    if( _mode == TMODE_SELECTION )
-    {
-      _updateSelectionIndices( );
-    }
-  }
-
-  const GIDUSet& DomainManager::selection( void )
-  {
-    return _selection;
-  }
-
-  tBoundingBox DomainManager::boundingBox( void ) const
-  {
-    tBoundingBox result = _boundingBox;
-
-    if( _boundingBox.first == _boundingBox.second )
-    {
-      result.second = _boundingBox.second + vec3( 0.1f, 0.1f, 0.1f );
+        break;
+      default:
+        break;
     }
 
-    return result;
-  }
-
-  prefr::ColorOperationModel* DomainManager::modelSelectionBase( void )
-  {
-    return _modelBase;
   }
 
-  void DomainManager::decay( float decayValue )
+  void DomainManager::applyDefaultShader( )
   {
-    _decayValue = decayValue;
-
-    _modelBase->setLife( decayValue, decayValue );
-    _modelHighlighted->setLife( decayValue, decayValue );
+    _currentRenderer = _defaultRenderer;
+    _selectionCluster->setRenderer( _currentRenderer );
+    for ( const auto& item: _groupClusters )
+      item.second->setRenderer( _currentRenderer );
+    for ( const auto& item: _attributeClusters )
+      item.second->setRenderer( _currentRenderer );
   }
 
-  float DomainManager::decay( void ) const
+  void DomainManager::applySolidShader( )
   {
-    return _decayValue;
+    _currentRenderer = _solidRenderer;
+    _selectionCluster->setRenderer( _currentRenderer );
+    for ( const auto& item: _groupClusters )
+      item.second->setRenderer( _currentRenderer );
+    for ( const auto& item: _attributeClusters )
+      item.second->setRenderer( _currentRenderer );
   }
 
-  void DomainManager::clearSelection( void )
+  void DomainManager::processInput(
+    const simil::SpikesCRange& spikes , bool killParticles )
   {
-    _selection.clear( );
-
-    if( _mode == TMODE_SELECTION )
+    switch ( _mode )
     {
-      _updateSelectionIndices( );
+      case VisualMode::Selection:
+        processSelectionSpikes( spikes , killParticles );
+        break;
+      case VisualMode::Groups:
+        processGroupSpikes( spikes , killParticles );
+        break;
+      case VisualMode::Attribute:
+        processAttributeSpikes( spikes , killParticles );
+        break;
+      default:
+        break;
     }
   }
 
-  void DomainManager::resetParticles( void )
+  std::unordered_map< uint32_t , float >
+  DomainManager::parseInput( const simil::SpikesCRange& spikes )
   {
-    _particleSystem->run( false );
+    std::unordered_map< uint32_t , float > result;
 
-    auto particles = _particleSystem->retrieveActive( );
-    for( int i = 0; i < static_cast<int>( particles.size( )); ++i )
+    for ( simil::SpikesCIter spike = spikes.first;
+          spike != spikes.second; ++spike )
     {
-      particles.at( i ).set_life( 0 );
+      if ( result.count( spike->second ) == 0 )
+      {
+        result[ spike->second ] = spike->first;
+      }
     }
-
-    _particleSystem->run( true );
-
-    _particleSystem->update( 0.0f );
-  }
-
-  const std::vector< VisualGroup* >& DomainManager::groups( void ) const
-  {
-    return _groups;
-  }
-
-  const std::vector< VisualGroup* >& DomainManager::attributeGroups( void ) const
-  {
-    return _attributeGroups;
-  }
-
-  const std::vector< std::pair< QColor, QColor >>&
-    DomainManager::paletteColors( void ) const
-  {
-    return _paletteColors;
-  }
-
-  const std::vector< std::string >& DomainManager::namesMorpho( void ) const
-  {
-    return _namesTypesMorpho;
-  }
-  const std::vector< std::string >& DomainManager::namesFunction( void ) const
-  {
-    return _namesTypesFunction;
-  }
-
-  std::pair<QColor, QColor> DomainManager::generateColorPair(
-      scoop::Color &color)
-  {
-    constexpr float brightFactor = 0.4f;
-    constexpr float darkFactor = 1.0f - brightFactor;
-
-    const glm::vec4 baseColor( color.red( ) * invRGBInt,
-                               color.green( ) * invRGBInt,
-                               color.blue( ) * invRGBInt, 0.6f );
-
-    color = QColor( baseColor.r * 255,
-                    baseColor.g * 255,
-                    baseColor.b * 255,
-                    baseColor.a * 255 );
-
-    const glm::vec4 darkColor =
-        ( baseColor * brightFactor ) + ( glm::vec4( 0.1f, 0.1f, 0.1f, 0.4f ) * darkFactor );
-
-    const QColor darkqColor = QColor( darkColor.r * 255,
-                                      darkColor.g * 255,
-                                      darkColor.b * 255,
-                                      darkColor.a * 255 );
-
-    return std::make_pair( color, darkqColor );
+    return result;
   }
 
-#ifdef SIMIL_USE_BRION
-
-  tNeuronAttribs DomainManager::_loadNeuronTypes( const brion::BlueConfig& blueConfig )
+  void DomainManager::processSelectionSpikes(
+    const simil::SpikesCRange& spikes , bool killParticles )
   {
-    tNeuronAttribs result;
-
-    const auto& gids = _gids;
+    auto input = parseInput( spikes );
 
-    try
+    auto map = _selectionCluster->mapData( );
+    const uint32_t size = _selectionCluster->size( );
+    for ( uint32_t i = 0; i < size; i++ )
     {
-      brion::Circuit circuit( blueConfig.getCircuitSource( ));
-
-      uint32_t attributes = brion::NEURON_COLUMN_GID |
-                            brion::NEURON_MTYPE |
-                            brion::NEURON_ETYPE;
-
-
-      const brion::NeuronMatrix& attribsData = circuit.get( gids, attributes );
-
-      _namesTypesMorpho = circuit.getTypes( brion::NEURONCLASS_MORPHOLOGY_CLASS );
-      _namesTypesFunction = circuit.getTypes( brion::NEURONCLASS_FUNCTION_CLASS );
-
-      _typesMorpho.reserve( gids.size( ));
-      _typesFunction.reserve( gids.size( ));
-
-      for( unsigned int i = 0; i < gids.size( ); ++i )
+      auto particle = map + i;
+      if ( killParticles )
       {
-        const unsigned int morphoType =
-            boost::lexical_cast< unsigned int >( attribsData[ i ][ 1 ]);
-
-        const unsigned int functionType =
-            boost::lexical_cast< unsigned int >( attribsData[ i ][ 2 ]);
-
-        _typesMorpho.push_back( morphoType );
-        _typesFunction.push_back( functionType );
+        particle->timestamp = -std::numeric_limits< float >::infinity( );
       }
 
-    }
-    catch( ... )
-    {
-      brain::Circuit circuit( blueConfig );
-      _namesTypesMorpho = circuit.getMorphologyTypeNames( );
-      _namesTypesFunction = circuit.getElectrophysiologyTypeNames( );
-
-      auto transform = [](const std::vector<size_t> &vec)
+      auto gid = _selectionGids.at( i );
+      auto value = input.find( gid );
+      if ( value != input.cend( ))
       {
-          std::vector<unsigned long> vec32;
-          vec32.reserve(vec.size());
-
-          std::for_each(vec.cbegin(), vec.cend(), [&vec32](const size_t num) { vec32.emplace_back(static_cast<unsigned long>(num)); });
-
-          return vec32;
-      };
-
-      _typesMorpho = transform(circuit.getMorphologyTypes( gids ));
-      _typesFunction = transform(circuit.getElectrophysiologyTypes( gids ));
-
+        particle->timestamp = value->second;
+      }
     }
 
-    unsigned int counter = 0;
+    _selectionCluster->unmapData( );
+  }
 
-    for( auto gid : gids )
+  void DomainManager::processGroupSpikes( const simil::SpikesCRange& spikes ,
+                                          bool killParticles )
+  {
+    auto input = parseInput( spikes );
+    for ( const auto& item: _groupClusters )
     {
-      NeuronAttributes attribs;
-
-      for( unsigned int i = 0; i < ( unsigned int ) T_TYPE_UNDEFINED; ++i )
+      auto cluster = item.second->getCluster( );
+      auto map = cluster->mapData( );
+      uint32_t size = cluster->size( );
+      for ( uint32_t i = 0; i < size; i++ )
       {
-        unsigned int typeValue =
-            (( i == 0 ) ? _typesMorpho : _typesFunction )[ counter ];
-
-        auto& stats = (( i == 0 ) ? _statsMorpho : _statsFunction );
-
-        auto& indexBack =
-            ( i == 0 ) ? _idxToTypeMorpho : _idxToTypeFunction;
-
-        auto attribFunctor =
-            ( i == 0 ) ?  &std::get< T_TYPE_MORPHO >( attribs ) :
-                           &std::get< T_TYPE_FUNCTION >( attribs );
-
-        auto statsIt = stats.find( typeValue );
-        if( statsIt == stats.end( ))
-          statsIt = stats.insert( std::make_pair( typeValue, 0 )).first;
-
-        ++statsIt->second;
-
-        indexBack.insert( std::make_pair( i, typeValue ));
-
-        *attribFunctor = typeValue;
+        auto particle = map + i;
+        if ( killParticles )
+        {
+          particle->timestamp = -std::numeric_limits< float >::infinity( );
+        }
+        auto gid = item.second->getGids().at( i );
+        auto value = input.find( gid );
+        if ( value != input.cend( ))
+        {
+          particle->timestamp = value->second;
+        }
       }
 
-      ++counter;
-
-      result.insert( std::make_pair( gid, attribs ));
+      cluster->unmapData( );
     }
+  }
 
-
-    if( _autoGroupByName )
+  void
+  DomainManager::processAttributeSpikes( const simil::SpikesCRange& spikes ,
+                                         bool killParticles )
+  {
+    auto input = parseInput( spikes );
+    for ( const auto& item: _attributeClusters )
     {
-      for( unsigned int i = 0; i < ( unsigned int ) T_TYPE_UNDEFINED; ++i )
+      auto cluster = item.second->getCluster( );
+      auto map = cluster->mapData( );
+      const uint32_t size = cluster->size( );
+      for ( uint32_t i = 0; i < size; i++ )
       {
-        const auto& names = ( i == 0 ) ? _namesTypesMorpho : _namesTypesFunction;
-        auto& groupedNameStorage =
-            ( i == 0 ) ? _namesTypesMorphoGrouped : _namesTypesFunctionGrouped;
-
-        auto& groupedIndices =
-            ( i == 0 ) ? _typeToIdxMorpho : _typeToIdxFunction;
-
-        auto& nameIndexer = ( i == 0 ) ? _namesIdxMorpho : _namesIdxFunction;
-
-        const auto& stats = (( i == 0 ) ? _statsMorpho : _statsFunction );
-
-        counter = 0;
-        for( auto name : names )
+        auto particle = map + i;
+        if ( killParticles )
         {
-
-          if( stats.find( counter ) != stats.end( ))
-          {
-
-            auto nameIndex = nameIndexer.find( name );
-            if( nameIndex == nameIndexer.end( ))
-            {
-              unsigned int index = nameIndexer.size( );
-              nameIndex = nameIndexer.insert( std::make_pair( name, index )).first;
-            }
-
-            groupedIndices.insert( std::make_pair( counter, nameIndex->second ));
-          }
-
-          ++counter;
-
+          particle->timestamp = -std::numeric_limits< float >::infinity( );
         }
-        std::cout << std::endl;
-
-        groupedNameStorage.resize( nameIndexer.size( ));
-
-        for( auto name : nameIndexer )
+        auto gid = item.second->getGids().at( i );
+        auto value = input.find( gid );
+        if ( value != input.cend( ))
         {
-          groupedNameStorage[ name.second ] = name.first;
+          particle->timestamp = value->second;
         }
-
-        if( groupedNameStorage.size( ) != names.size( ))
-          _groupByName = true;
       }
-    }
 
-//    std::cout << "Loaded attributes." << std::endl;
-//    std::cout << "- Morphological: " << std::endl;
-//    for( auto type : _statsMorpho )
-//      std::cout << _namesTypesMorpho[ type.first ]
-//                << " -> " << type.first
-//                << " # " << type.second
-//                << std::endl;
-//
-//    std::cout << " Grouped in: " << std::endl;
-//    for( auto type : _namesIdxMorpho )
-//      std::cout << type.second << ": " << type.first << std::endl;
-//
-//    std::cout << "- Functional: " << std::endl;
-//    for( auto type : _statsFunction )
-//      std::cout << _namesTypesFunction[ type.first ]
-//                << " -> " << type.first
-//                << " # " << type.second
-//                << std::endl;
-//
-//    std::cout << " Grouped in: " << std::endl;
-//    for( auto type : _namesIdxFunction )
-//      std::cout << type.second << ": " << type.first << std::endl;
-
-    return result;
+      cluster->unmapData( );
+    }
   }
-#endif // SIMIL_USE_BRION
-
-  const std::vector< long unsigned int >& DomainManager::attributeValues( int attribNumber ) const
-   {
-     if(( tNeuronAttributes )attribNumber == T_TYPE_MORPHO )
-       return _typesMorpho;
-     else
-       return _typesFunction;
-   }
-
-   Strings DomainManager::attributeNames( int attribNumber, bool  ) const
-   {
-     Strings result;
-
-     if( _groupByName )
-     {
-       result = ( attribNumber == 0 ) ? _namesTypesMorphoGrouped :
-                                       _namesTypesFunctionGrouped;
-     }
-     else
-     {
-       const auto& namesIdx = ( attribNumber == 0 ) ? _namesIdxMorpho : _namesIdxFunction;
-
-       result.resize( namesIdx.size( ));
-
-       for( auto name : namesIdx )
-       {
-         result[ name.second ] = name.first;
-       }
-
-     }
-     result.shrink_to_fit( );
-
-     return result;
-   }
-
-   tAppStats DomainManager::attributeStatistics( void ) const
-   {
-     tAppStats result;
-
-     const auto& stats =
-         ( _currentAttrib == T_TYPE_MORPHO ) ? _statsMorpho : _statsFunction;
-
-     const auto& typeIdx =
-         ( _currentAttrib == T_TYPE_MORPHO ) ? &_typeToIdxMorpho : &_typeToIdxFunction;
-
-     const auto& nameIndices =
-         ( _currentAttrib == T_TYPE_MORPHO ) ? _namesIdxMorpho : _namesIdxFunction;
-
-     unsigned int numberOfValues = nameIndices.size( );
-
-     result.resize( numberOfValues );
-
-     std::vector< unsigned int > statsTotal( numberOfValues, 0 );
-
-     for( auto valueStats : stats )
-     {
-       unsigned int index = typeIdx->find( valueStats.first )->second;
-
-       statsTotal[ index ] += valueStats.second;
-     }
-
-     for( auto attrib : nameIndices )
-     {
-       auto& name = attrib.first;
-
-       auto idxIt = nameIndices.find( name );
-       unsigned int idx = idxIt->second;
-
-       unsigned int value = statsTotal[ idx ];
-
-       std::string label = "";
-       auto labelIt = _attributeNameLabels.find( name );
-       if( labelIt != _attributeNameLabels.end( ))
-         label = labelIt->second;
-
-       tStatsGroup attribs = std::make_tuple( 0, name, label, value );
-
-       result[ idx ] = attribs;
-     }
-
-     return result;
-   }
-
-   tParticleInfo DomainManager::pickingInfoSimple( unsigned int particleId ) const
-   {
-     tParticleInfo result;
-
-     unsigned int gid = 0;
-     bool valid = false;
-     vec3 position( 0, 0, 0 );
-     QPoint screenPos( 0, 0 );
-
-     auto gidIt = _particleToGID.find( particleId );
-     if( gidIt != _particleToGID.end( ))
-     {
-       gid = gidIt->second;
-
-       auto particle = _particleSystem->particles( ).at( particleId );
-
-       position = particle.position( );
-
-       valid = true;
-     }
-
-     std::get< T_PART_GID >( result ) = gid;
-     std::get< T_PART_INTERNAL_GID >( result ) = particleId;
-     std::get< T_PART_POSITION >( result ) = position;
-     std::get< T_PART_SCREEN_POS >( result ) = screenPos;
-     std::get< T_PART_VALID >( result ) = valid;
-
-     return result;
-   }
-
-   void DomainManager::highlightElements( const std::unordered_set< unsigned int >& highlighted )
-   {
-     clearHighlighting( );
-
-     prefr::ParticleIndices indices;
-     indices.reserve( highlighted.size( ));
-
-     for( auto gid : highlighted )
-       indices.push_back( gid );
-
-     _clusterHighlighted->particles( ).indices( indices );
-
-     _clusterHighlighted->setModel( _modelHighlighted );
-
-   }
-
-   void DomainManager::clearHighlighting( void )
-   {
-     if( _mode == TMODE_SELECTION )
-     {
-       _clusterSelected->setModel( _modelBase );
-       _clusterUnselected->setModel( _modelOff );
-     }
-     else
-     {
-       auto groupArray = ( _mode == TMODE_GROUPS ) ? _groups : _attributeGroups;
-
-       for( auto group : groupArray )
-       {
-         group->cluster( )->setModel( group->model( ));
-       }
-     }
-   }
 }
diff --git a/visimpl/DomainManager.h b/visimpl/DomainManager.h
index b8894d0431255eef68d0efb3af8c02f1a15a0c35..2a8dc65d60d3809949a5c49b0facb282eba2ee01 100644
--- a/visimpl/DomainManager.h
+++ b/visimpl/DomainManager.h
@@ -1,257 +1,155 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __VISIMPL_VISUALGROUPMANAGER__
-#define __VISIMPL_VISUALGROUPMANAGER__
-
-#include <unordered_map>
-
-#include <prefr/prefr.h>
-#include <prefr/GL/IGLRenderProgram.h>
-#include <simil/simil.h>
-#include <scoop/scoop.h>
-
-#include <sumrice/sumrice.h>
+//
+// Created by gaeqs on 21/06/22.
+//
 
-#include "types.h"
+#ifndef VISIMPL_DOMAINMANAGER_H
+#define VISIMPL_DOMAINMANAGER_H
+
+#include <map>
+
+// ParticleLab
+#include <plab/plab.h>
+
+#include "visimpl/particlelab/NeuronParticle.h"
 #include "VisualGroup.h"
-#include "prefr/ColorOperationModel.h"
-#include "prefr/SourceMultiPosition.h"
+
+#include "types.h"
 
 namespace visimpl
 {
-  enum tVisualMode
+  enum class VisualMode
   {
-    TMODE_SELECTION = 0,
-    TMODE_GROUPS,
-    TMODE_ATTRIBUTE,
-    TMODE_UNDEFINED
+    Selection = 0 ,
+    Groups ,
+    Attribute ,
+    Undefined
   };
 
+
   class DomainManager
   {
-  public:
-
-    DomainManager( prefr::ParticleSystem* particleSystem, const TGIDSet& gids );
-
-#ifdef SIMIL_USE_BRION
-    void init( const tGidPosMap& positions, const brion::BlueConfig* blueConfig );
-#else
-    void init( const tGidPosMap& positions );
-#endif
-
-
-    void initializeParticleSystem( prefr::IGLRenderProgram* program );
-
-    VisualGroup* addVisualGroupFromSelection( const std::string& name,
-                                              bool overrideGIDs = false );
-    VisualGroup* addVisualGroup( const GIDUSet& group_, const std::string& name,
-                                 bool overrideGIDs = false );
-
-    void setVisualGroupState( unsigned int i, bool state, bool attrib = false );
-    void removeVisualGroup( unsigned int i );
-
-    void showInactive( bool state );
-
-
-    void generateAttributesGroups( tNeuronAttributes attrib );
-
-    void processInput( const simil::SpikesCRange& spikes_,
-                       float begin, float end, bool clear );
-
-    void update( void );
-
-    void updateData(const TGIDSet& gids,const tGidPosMap& positions);
-
-    void mode(const tVisualMode newMode );
-    tVisualMode mode( void ) const;
-
-    void clearView( void );
-
-    bool showGroups( void );
-    void updateGroups( void );
-    void updateAttributes( void );
 
-    void selection( const GIDUSet& newSelection );
-    const GIDUSet& selection( void );
+    VisualMode _mode;
+    std::shared_ptr< plab::ICamera > _camera;
 
-    void decay( float decayValue );
-    float decay( void ) const;
+    std::vector< uint32_t > _selectionGids;
+    std::shared_ptr< plab::Cluster< NeuronParticle > > _selectionCluster;
 
-    void clearSelection( void );
-    void resetParticles( void );
+    std::map< std::string , std::shared_ptr< VisualGroup > > _groupClusters;
 
-    const std::vector< VisualGroup* >& groups( void ) const;
-    const std::vector< VisualGroup* >& attributeGroups( void ) const;
+    std::map< std::string , std::shared_ptr< VisualGroup > > _attributeClusters;
+    std::map< tNeuronAttributes , std::vector< std::string>> _attributeNames;
+    std::map< tNeuronAttributes , std::vector< std::vector< uint32_t>> > _attributeTypeGids;
 
-    const tGidPosMap& positions( void ) const;
+    // Models
+    std::shared_ptr< StaticGradientModel > _selectionModel;
 
-    void reloadPositions( void );
+    // Renders
+    reto::ShaderProgram _defaultProgram;
+    reto::ShaderProgram _solidProgram;
 
+    std::shared_ptr< plab::CoverageRenderer > _currentRenderer;
+    std::shared_ptr< plab::CoverageRenderer > _defaultRenderer;
+    std::shared_ptr< plab::CoverageRenderer > _solidRenderer;
 
-    const TGIDSet& gids( void ) const;
-
-    tBoundingBox boundingBox( void ) const;
-
-    prefr::ColorOperationModel* modelSelectionBase( void );
-
-    const std::vector< std::pair< QColor, QColor >>& paletteColors( void ) const;
-
-    // Statistics
-    const std::vector< std::string >& namesMorpho( void ) const;
-    const std::vector< std::string >& namesFunction( void ) const;
-
-    const std::vector< long unsigned int >& attributeValues( int attribNumber ) const;
-    Strings attributeNames( int attribNumber, bool labels = false ) const;
-
-    tAppStats attributeStatistics( void ) const;
-
-    tParticleInfo pickingInfoSimple( unsigned int particleId ) const;
-
-    void highlightElements( const std::unordered_set< unsigned int >& highlighted );
-    void clearHighlighting( void );
-
-    /** \brief Helper method to generate que QColor pair from a given color.
-     * \param[inout] c scoop::Color object reference.
-     *
-     */
-    static std::pair<QColor, QColor> generateColorPair(scoop::Color &c);
-
-  protected:
-
-    typedef std::vector< std::tuple< uint32_t, float >> TModifiedNeurons;
-
-    TModifiedNeurons _parseInput( const simil::SpikesCRange& spikes_,
-                                 float begin, float end );
-
-
-    VisualGroup* _generateGroup( const GIDUSet& gids, const std::string& name,
-                                 unsigned int idx ) const;
+    // Others
+    tBoundingBox _boundingBox;
+    float _decay;
 
-    void _updateGroupsModels( void );
-    void _generateGroupsIndices( void );
+  public:
 
-    void _updateSelectionIndices( void );
-    void _generateSelectionIndices( void );
+    DomainManager( );
 
-    void _updateAttributesIndices( void );
-    void _generateAttributesIndices( void );
+    void initRenderers(
+      const std::shared_ptr< reto::ClippingPlane >& leftPlane ,
+      const std::shared_ptr< reto::ClippingPlane >& rightPlane ,
+      const std::shared_ptr< plab::ICamera >& camera );
 
-    void _processFrameInputSelection( const simil::SpikesCRange& spikes_,
-                                      float begin, float end );
-    void _processFrameInputGroups( const simil::SpikesCRange& spikes_,
-                                   float begin, float end );
-    void _processFrameInputAttributes( const simil::SpikesCRange& spikes_,
-                                       float begin, float end );
+#ifdef SIMIL_USE_BRION
 
-    void _loadPaletteColors( void );
+    void initAttributeData( const TGIDSet& gids ,
+                            const brion::BlueConfig* blueConfig );
 
-    void _clearSelectionView( void );
-    void _clearGroupsView( void );
-    void _clearAttribView( void );
+#endif
 
-    void _clearGroups( void );
-    void _clearAttribs( bool clearCustom = true );
+    std::shared_ptr< plab::Cluster< NeuronParticle > >
+    getSelectionCluster( ) const;
 
-    void _clearGroup( VisualGroup* group, bool clearState = true );
-    void _clearParticlesReference( void );
+    const std::shared_ptr< StaticGradientModel >& getSelectionModel( ) const;
 
-    void _resetBoundingBox( void );
+    int getGroupAmount( ) const;
 
-    SourceMultiPosition* _getSource( unsigned int numParticles );
+    const std::map< std::string , std::shared_ptr< VisualGroup>>&
+    getGroups( ) const;
 
-#ifdef SIMIL_USE_BRION
-    tNeuronAttribs _loadNeuronTypes( const brion::BlueConfig& blueConfig );
-#endif
+    std::shared_ptr< VisualGroup > getGroup( const std::string& name ) const;
 
-    prefr::ParticleSystem* _particleSystem;
+    const std::map< std::string , std::shared_ptr< VisualGroup>>&
+    getAttributeClusters( ) const;
 
-    tGidPosMap _gidPositions;
+    VisualMode getMode( ) const;
 
-    TGIDSet _gids;
+    void setMode( VisualMode mode );
 
-    prefr::Cluster* _clusterSelected;
-    prefr::Cluster* _clusterUnselected;
-    prefr::Cluster* _clusterHighlighted;
+    float getDecay( ) const;
 
-    SourceMultiPosition* _sourceSelected;
+    void setDecay( float decay );
 
-    std::vector< VisualGroup* > _groups;
-    std::vector< VisualGroup* > _attributeGroups;
-    tNeuronAttributes _currentAttrib;
+    void setTime( float time );
 
-    std::unordered_map< uint32_t, VisualGroup* > _neuronGroup;
+    void addTime( float time, float endTime );
 
-    std::unordered_map< unsigned int, SourceMultiPosition* > _gidSource;
+    const tBoundingBox& getBoundingBox( ) const;
 
-    tUintUMap _gidToParticle;
-    tUintUMap _particleToGID;
+    void setSelection( const TGIDSet& gids ,
+                       const tGidPosMap& positions );
 
-    prefr::ColorOperationModel* _modelBase;
-    prefr::ColorOperationModel* _modelOff;
-    prefr::ColorOperationModel* _modelHighlighted;
+    void setSelection( const GIDUSet& gids ,
+                       const tGidPosMap& positions );
 
-    prefr::PointSampler* _sampler;
-    prefr::Updater* _updater;
+    std::shared_ptr< VisualGroup > createGroup( const GIDUSet& gids ,
+                                                const tGidPosMap& positions ,
+                                                const std::string& name );
 
-    tVisualMode _mode;
+    std::shared_ptr< VisualGroup > createGroupFromSelection(
+      const tGidPosMap& positions , const std::string& name );
 
-    GIDUSet _selection;
+    void removeGroup( const std::string& name );
 
-    float _decayValue;
+    void selectAttribute(
+      const std::vector< QColor >& colors ,
+      const tGidPosMap& positions ,
+      tNeuronAttributes attribute );
 
-    bool _showInactive;
+    void applyDefaultShader( );
 
-    tBoundingBox _boundingBox;
+    void applySolidShader( );
 
-    std::vector< std::pair< QColor, QColor >> _paletteColors;
+    void enableAccumulativeMode( bool enabled );
 
-    // Statistics
-    bool _groupByName;
-    bool _autoGroupByName;
+    void enableClipping( bool enabled );
 
-    tNeuronAttribs _gidTypes;
+    void draw( ) const;
 
-    std::vector< std::string > _namesTypesMorpho;
-    std::vector< std::string > _namesTypesFunction;
+    void processInput(
+      const simil::SpikesCRange& spikes , bool killParticles );
 
-    std::vector< std::string > _namesTypesMorphoGrouped;
-    std::vector< std::string > _namesTypesFunctionGrouped;
+  protected:
 
-    std::vector< long unsigned int > _typesMorpho;
-    std::vector< long unsigned int > _typesFunction;
+    std::unordered_map< uint32_t , float >
+    parseInput( const simil::SpikesCRange& spikes );
 
-    tUintUMap _typeToIdxMorpho;
-    tUintUMap _typeToIdxFunction;
+    void processSelectionSpikes(
+      const simil::SpikesCRange& spikes , bool killParticles );
 
-    tUintUMultimap _idxToTypeMorpho;
-    tUintUMultimap _idxToTypeFunction;
+    void processGroupSpikes(
+      const simil::SpikesCRange& spikes , bool killParticles );
 
-    tUintUMap _statsMorpho;
-    tUintUMap _statsFunction;
+    void processAttributeSpikes(
+      const simil::SpikesCRange& spikes , bool killParticles );
 
-    std::unordered_map< std::string, unsigned int > _namesIdxMorpho;
-    std::unordered_map< std::string, unsigned int > _namesIdxFunction;
   };
+
 }
 
-#endif /* __VISIMPL_VISUALGROUPMANAGER__ */
+#endif //VISIMPL_DOMAINMANAGER_H
diff --git a/visimpl/GlewInitializer.cpp b/visimpl/GlewInitializer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2d12a314541c56775507d9d5c408198cbcaf8cce
--- /dev/null
+++ b/visimpl/GlewInitializer.cpp
@@ -0,0 +1,27 @@
+//
+// Created by gaeqs on 6/28/22.
+//
+
+#include "GlewInitializer.h"
+#include <GL/glew.h>
+
+namespace visimpl {
+
+  bool GlewInitializer::_initialized = false;
+
+  void GlewInitializer::init( void )
+  {
+    if ( !_initialized )
+    {
+      glewExperimental = GL_TRUE;
+      glewInit( );
+      _initialized = true;
+    }
+  }
+
+  bool GlewInitializer::isInitialized( void )
+  {
+    return _initialized;
+  }
+
+}
\ No newline at end of file
diff --git a/visimpl/GlewInitializer.h b/visimpl/GlewInitializer.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f8ad841adc6c9c2bccc1e4bb006e145b0546223
--- /dev/null
+++ b/visimpl/GlewInitializer.h
@@ -0,0 +1,26 @@
+//
+// Created by gaeqs on 6/28/22.
+//
+
+#ifndef VISIMPL_GLEWINITIALIZER_H
+#define VISIMPL_GLEWINITIALIZER_H
+
+
+namespace visimpl
+{
+
+  class GlewInitializer
+  {
+
+    static bool _initialized;
+
+  public:
+    static void init( );
+
+    static bool isInitialized( );
+
+  };
+}
+
+
+#endif //VISIMPL_GLEWINITIALIZER_H
diff --git a/visimpl/MainWindow.cpp b/visimpl/MainWindow.cpp
index 263b28b698d62824e91cf35e5819737c5513d620..ffabe20eb1bb8c68c41306aea917919c4a1e16d3 100644
--- a/visimpl/MainWindow.cpp
+++ b/visimpl/MainWindow.cpp
@@ -21,15 +21,22 @@
  */
 
 #ifdef VISIMPL_USE_GMRVLEX
+
 #include <gmrvlex/version.h>
+
 #endif
 #ifdef VISIMPL_USE_ZEROEQ
+
 #include <zeroeq/version.h>
+
 #endif
 #ifdef VISIMPL_USE_RETO
+
 #include <reto/version.h>
+
 #endif
 #ifdef VISIMPL_USE_SCOOP
+
 #include <scoop/version.h>
 
 #endif
@@ -76,29 +83,30 @@
 
 #include <sumrice/sumrice.h>
 
-template<class T> void ignore( const T& ) { }
+template< class T >
+void ignore( const T& )
+{ }
 
 constexpr const char* POSITION_KEY = "positionData";
 constexpr const char* PLANES_COLOR_KEY = "clippingPlanesColor";
-constexpr const char* GROUP_KEY = "groupNum";
-constexpr const char* GROUP_POINTER_KEY = "groupPtr";
+constexpr const char* GROUP_NAME = "groupName";
 
 namespace visimpl
 {
   enum toolIndex
   {
-    T_TOOL_Playback = 0,
-    T_TOOL_Visual,
-    T_TOOL_Selection,
+    T_TOOL_Playback = 0 ,
+    T_TOOL_Visual ,
+    T_TOOL_Selection ,
     T_TOOL_Inpector
   };
 
-  MainWindow::MainWindow( QWidget* parent_, bool updateOnIdle )
+  MainWindow::MainWindow( QWidget* parent_ , bool updateOnIdle )
     : QMainWindow( parent_ )
     , _ui( new Ui::MainWindow )
     , _lastOpenedNetworkFileName( "" )
-    , _playIcon(":/icons/play.svg")
-    , _pauseIcon(":/icons/pause.svg")
+    , _playIcon( ":/icons/play.svg" )
+    , _pauseIcon( ":/icons/pause.svg" )
     , _openGLWidget( nullptr )
     , _domainManager( nullptr )
     , _subsetEvents( nullptr )
@@ -131,8 +139,8 @@ namespace visimpl
     , _circuitScaleZ( nullptr )
     , _buttonImportGroups( nullptr )
     , _buttonClearGroups( nullptr )
-    , _buttonLoadGroups{nullptr}
-    , _buttonSaveGroups{nullptr}
+    , _buttonLoadGroups{ nullptr }
+    , _buttonSaveGroups{ nullptr }
     , _buttonAddGroup( nullptr )
     , _buttonClearSelection( nullptr )
     , _selectionSizeLabel( nullptr )
@@ -153,17 +161,18 @@ namespace visimpl
     , _frameClippingColor( nullptr )
     , _buttonSelectionFromClippingPlanes( nullptr )
     , _recorder( nullptr )
-    , m_loader{nullptr}
-    , m_loaderDialog{nullptr}
+    , m_loader{ nullptr }
+    , m_loaderDialog{ nullptr }
   {
     _ui->setupUi( this );
 
-    auto recorderAction = RecorderUtils::recorderAction();
-    _ui->menuTools->insertAction(_ui->menuTools->actions().first(), recorderAction);
-    _ui->toolBar->addAction(recorderAction);
+    auto recorderAction = RecorderUtils::recorderAction( );
+    _ui->menuTools->insertAction( _ui->menuTools->actions( ).first( ) ,
+                                  recorderAction );
+    _ui->toolBar->addAction( recorderAction );
 
-    connect(recorderAction, SIGNAL(triggered(bool)),
-            this, SLOT(openRecorder()));
+    connect( recorderAction , SIGNAL( triggered( bool )) ,
+             this , SLOT( openRecorder( )) );
 
     _ui->actionUpdateOnIdle->setChecked( updateOnIdle );
     _ui->actionShowFPSOnIdleUpdate->setChecked( false );
@@ -176,14 +185,14 @@ namespace visimpl
     _ui->actionOpenBlueConfig->setEnabled( false );
 #endif
 
-    auto positionsMenu = new QMenu();
-    positionsMenu->setTitle("Camera positions");
-    _ui->actionCamera_Positions->setMenu(positionsMenu);
+    auto positionsMenu = new QMenu( );
+    positionsMenu->setTitle( "Camera positions" );
+    _ui->actionCamera_Positions->setMenu( positionsMenu );
   }
 
   void MainWindow::init( const std::string& zeqUri )
   {
-    _openGLWidget = new OpenGLWidget( this, Qt::WindowFlags(), zeqUri );
+    _openGLWidget = new OpenGLWidget( this , Qt::WindowFlags( ) , zeqUri );
 
     this->setCentralWidget( _openGLWidget );
 
@@ -191,15 +200,18 @@ namespace visimpl
 
     try
     {
-      auto &zInstance = ZeroEQConfig::instance();
-      if(!zInstance.isConnected())
+      auto& zInstance = ZeroEQConfig::instance( );
+      if ( !zInstance.isConnected( ))
       {
-        zInstance.connect(zeqUri);
+        zInstance.connect( zeqUri );
       }
 
-      zInstance.subscriber()->subscribe(lexis::data::SelectedIDs::ZEROBUF_TYPE_IDENTIFIER(),
-                                        [&](const void* data_, unsigned long long size_)
-                                        { _onSelectionEvent(lexis::data::SelectedIDs::create(data_,  size_));});
+      zInstance.subscriber( )->subscribe(
+        lexis::data::SelectedIDs::ZEROBUF_TYPE_IDENTIFIER( ) ,
+        [ & ]( const void* data_ , unsigned long long size_ )
+        {
+          _onSelectionEvent( lexis::data::SelectedIDs::create( data_ , size_ ));
+        } );
 
       // receive loop will be started by OpenGLWidget after loading data.
     }
@@ -216,48 +228,50 @@ namespace visimpl
 
 #endif
 
-    _openGLWidget->idleUpdate( _ui->actionUpdateOnIdle->isChecked( ) );
+    _openGLWidget->idleUpdate( _ui->actionUpdateOnIdle->isChecked( ));
 
-    connect( _ui->actionUpdateOnIdle, SIGNAL( triggered( void ) ),
-             _openGLWidget, SLOT( toggleUpdateOnIdle( void ) ) );
+    connect( _ui->actionUpdateOnIdle , SIGNAL( triggered( void )) ,
+             _openGLWidget , SLOT( toggleUpdateOnIdle( void )) );
 
-    connect( _ui->actionBackgroundColor, SIGNAL( triggered( void ) ),
-             _openGLWidget, SLOT( changeClearColor( void ) ) );
+    connect( _ui->actionBackgroundColor , SIGNAL( triggered( void )) ,
+             _openGLWidget , SLOT( changeClearColor( void )) );
 
-    connect( _openGLWidget, SIGNAL( planesColorChanged( const QColor & ) ),
-             this, SLOT( changePlanesColor( const QColor & ) ) );
+    connect( _openGLWidget , SIGNAL( planesColorChanged(
+                                       const QColor & )) ,
+             this , SLOT( changePlanesColor(
+                            const QColor & )) );
 
-    connect( _ui->actionShowFPSOnIdleUpdate, SIGNAL( triggered( void ) ),
-             _openGLWidget, SLOT( toggleShowFPS( void ) ) );
+    connect( _ui->actionShowFPSOnIdleUpdate , SIGNAL( triggered( void )) ,
+             _openGLWidget , SLOT( toggleShowFPS( void )) );
 
-    connect( _ui->actionShowEventsActivity, SIGNAL( triggered( bool ) ),
-             _openGLWidget, SLOT( showEventsActivityLabels( bool ) ) );
+    connect( _ui->actionShowEventsActivity , SIGNAL( triggered( bool )) ,
+             _openGLWidget , SLOT( showEventsActivityLabels( bool )) );
 
-    connect( _ui->actionShowCurrentTime, SIGNAL( triggered( bool ) ),
-             _openGLWidget, SLOT( showCurrentTimeLabel( bool ) ) );
+    connect( _ui->actionShowCurrentTime , SIGNAL( triggered( bool )) ,
+             _openGLWidget , SLOT( showCurrentTimeLabel( bool )) );
 
-    connect( _ui->actionOpenBlueConfig, SIGNAL( triggered( void ) ), this,
-             SLOT( openBlueConfigThroughDialog( void ) ) );
+    connect( _ui->actionOpenBlueConfig , SIGNAL( triggered( void )) , this ,
+             SLOT( openBlueConfigThroughDialog( void )) );
 
-    connect( _ui->actionOpenCSVFiles, SIGNAL( triggered( void ) ), this,
-             SLOT( openCSVFilesThroughDialog( void ) ) );
+    connect( _ui->actionOpenCSVFiles , SIGNAL( triggered( void )) , this ,
+             SLOT( openCSVFilesThroughDialog( void )) );
 
     connect( _ui->actionOpenH5Files , SIGNAL( triggered( void )) , this ,
              SLOT( openHDF5ThroughDialog( void )) );
 
     connect( _ui->actionConnectREST , SIGNAL( triggered( void )) , this ,
-             SLOT( openRESTThroughDialog()));
+             SLOT( openRESTThroughDialog( )) );
 
-    connect( _ui->actionConfigureREST, SIGNAL(triggered()), this,
-             SLOT(configureREST()));
+    connect( _ui->actionConfigureREST , SIGNAL( triggered( )) , this ,
+             SLOT( configureREST( )) );
 
     connect( _ui->actionOpenSubsetEventsFile , SIGNAL( triggered( void )) ,
              this , SLOT( openSubsetEventsFileThroughDialog( void )) );
 
-    _ui->actionOpenSubsetEventsFile->setEnabled(false);
+    _ui->actionOpenSubsetEventsFile->setEnabled( false );
 
 #ifdef SIMIL_WITH_REST_API
-    _ui->actionConnectREST->setEnabled(true);
+    _ui->actionConnectREST->setEnabled( true );
 #endif
 
     connect( _ui->actionCloseData , SIGNAL( triggered( void )) , this ,
@@ -273,24 +287,28 @@ namespace visimpl
              SLOT( home( void )) );
 
     connect( _openGLWidget , SIGNAL( stepCompleted( void )) , this ,
-             SLOT( completedStep( void )));
+             SLOT( completedStep( void )) );
 
     connect( _openGLWidget , SIGNAL( pickedSingle( unsigned int )) , this ,
              SLOT( updateSelectedStatsPickingSingle( unsigned int )) );
 
-    connect(_ui->actionAdd_camera_position, SIGNAL(triggered(bool)), this,
-             SLOT(addCameraPosition()));
+    connect( _ui->actionAdd_camera_position , SIGNAL( triggered( bool )) ,
+             this ,
+             SLOT( addCameraPosition( )) );
 
-    connect(_ui->actionRemove_camera_position, SIGNAL(triggered(bool)), this,
-             SLOT(removeCameraPosition()));
+    connect( _ui->actionRemove_camera_position , SIGNAL( triggered( bool )) ,
+             this ,
+             SLOT( removeCameraPosition( )) );
 
-    connect(_ui->actionLoad_camera_positions, SIGNAL(triggered(bool)), this,
-             SLOT(loadCameraPositions()));
+    connect( _ui->actionLoad_camera_positions , SIGNAL( triggered( bool )) ,
+             this ,
+             SLOT( loadCameraPositions( )) );
 
-    connect(_ui->actionSave_camera_positions, SIGNAL(triggered(bool)), this,
-             SLOT(saveCameraPositions()));
+    connect( _ui->actionSave_camera_positions , SIGNAL( triggered( bool )) ,
+             this ,
+             SLOT( saveCameraPositions( )) );
 
-    QAction *actionTogglePause = new QAction( this );
+    QAction* actionTogglePause = new QAction( this );
     actionTogglePause->setShortcut( Qt::Key_Space );
 
     connect( actionTogglePause , SIGNAL( triggered( )) , this ,
@@ -310,7 +328,7 @@ namespace visimpl
     _initPlaybackDock( );
     _initSimControlDock( );
     _initStackVizDock( );
-    _ui->actionToggleStackVizDock->setEnabled(false);
+    _ui->actionToggleStackVizDock->setEnabled( false );
 
     connect(
       _simulationDock->toggleViewAction( ) , SIGNAL( toggled( bool )) ,
@@ -339,9 +357,9 @@ namespace visimpl
 
     connect(
       _stackVizDock->toggleViewAction( ) , SIGNAL( toggled( bool )) ,
-      this, SLOT( changeStackVizToolbarStatus(bool))
+      this , SLOT( changeStackVizToolbarStatus( bool ))
     );
-    changeStackVizToolbarStatus(false);
+    changeStackVizToolbarStatus( false );
 
     connect(
       _ui->actionToggleStackVizDock , SIGNAL( triggered( )) ,
@@ -356,9 +374,9 @@ namespace visimpl
   {
 #ifdef VISIMPL_USE_ZEROEQ
 
-    auto &instance = ZeroEQConfig::instance();
-    if(instance.isConnected())
-      instance.disconnect();
+    auto& instance = ZeroEQConfig::instance( );
+    if ( instance.isConnected( ))
+      instance.disconnect( );
 
 #endif
     delete _ui;
@@ -376,35 +394,36 @@ namespace visimpl
   {
     _domainManager = _openGLWidget->domainManager( );
 
-    _selectionManager->setGIDs( _domainManager->gids( ) );
+    _selectionManager->setGIDs( _openGLWidget->player( )->gids( ));
 
-    _subsetEvents = _openGLWidget->subsetEventsManager();
+    _subsetEvents = _openGLWidget->subsetEventsManager( );
 
-    _ui->actionToggleStackVizDock->setEnabled(true);
-    _ui->actionOpenSubsetEventsFile->setEnabled(true);
-    _ui->actionCloseData->setEnabled(true);
+    _ui->actionToggleStackVizDock->setEnabled( true );
+    _ui->actionOpenSubsetEventsFile->setEnabled( true );
+    _ui->actionCloseData->setEnabled( true );
 
-    _buttonImportGroups->setEnabled( _subsetEvents && _subsetEvents->numSubsets() > 0 );
+    _buttonImportGroups->setEnabled(
+      _subsetEvents && _subsetEvents->numSubsets( ) > 0 );
 
-    if(_openGLWidget)
+    if ( _openGLWidget )
     {
-      auto player = _openGLWidget->player();
-      if(player)
+      auto player = _openGLWidget->player( );
+      if ( player )
       {
-        const auto tBegin = player->startTime();
-        const auto tEnd = player->endTime();
-        const auto tCurrent = player->currentTime();
+        const auto tBegin = player->startTime( );
+        const auto tEnd = player->endTime( );
+        const auto tCurrent = player->currentTime( );
 
-        _startTimeLabel->setText(QString::number(tCurrent, 'f', 3));
-        _endTimeLabel->setText(QString::number(tEnd, 'f', 3));
+        _startTimeLabel->setText( QString::number( tCurrent , 'f' , 3 ));
+        _endTimeLabel->setText( QString::number( tEnd , 'f' , 3 ));
 
-        const auto percentage = (tCurrent - tBegin) / (tEnd - tBegin);
-        UpdateSimulationSlider(percentage);
+        const auto percentage = ( tCurrent - tBegin ) / ( tEnd - tBegin );
+        UpdateSimulationSlider( percentage );
       }
     }
 
-    _simulationDock->setEnabled(true);
-    _simConfigurationDock->setEnabled(true);
+    _simulationDock->setEnabled( true );
+    _simConfigurationDock->setEnabled( true );
   }
 
   void MainWindow::openBlueConfigThroughDialog( void )
@@ -412,56 +431,62 @@ namespace visimpl
 #ifdef SIMIL_USE_BRION
 
     QString path = QFileDialog::getOpenFileName(
-      this, tr( "Open BlueConfig" ), _lastOpenedNetworkFileName,
-      tr( "BlueConfig ( BlueConfig CircuitConfig);; All files (*)" ), nullptr,
+      this , tr( "Open BlueConfig" ) , _lastOpenedNetworkFileName ,
+      tr( "BlueConfig ( BlueConfig CircuitConfig);; All files (*)" ) , nullptr ,
       QFileDialog::DontUseNativeDialog );
 
-    if ( !path.isEmpty() )
+    if ( !path.isEmpty( ))
     {
       bool ok;
 
-      QString text = QInputDialog::getText( this, tr( "Please type a target" ),
-                                            tr( "Target name:" ),
-                                            QLineEdit::Normal, "Mosaic", &ok );
+      QString text = QInputDialog::getText( this ,
+                                            tr( "Please type a target" ) ,
+                                            tr( "Target name:" ) ,
+                                            QLineEdit::Normal , "Mosaic" ,
+                                            &ok );
 
-      if ( ok && !text.isEmpty( ) )
+      if ( ok && !text.isEmpty( ))
       {
         std::string reportLabel = text.toStdString( );
         _lastOpenedNetworkFileName = QFileInfo( path ).path( );
         std::string fileName = path.toStdString( );
 
-        loadData(simil::TBlueConfig, fileName, reportLabel, simil::TSimSpikes);
+        loadData( simil::TBlueConfig , fileName , reportLabel ,
+                  simil::TSimSpikes );
       }
     }
 #else
-    const QString title = tr("Open BlueConfig");
-    const QString message = tr("BlueConfig loading is not supported in this version.");
-    QMessageBox::critical(this, title, message, QMessageBox::Button::Ok);
+    const QString title = tr( "Open BlueConfig" );
+    const QString message = tr(
+      "BlueConfig loading is not supported in this version." );
+    QMessageBox::critical( this , title , message , QMessageBox::Button::Ok );
 #endif
   }
 
   void MainWindow::openCSVFilesThroughDialog( void )
   {
     QString pathNetwork = QFileDialog::getOpenFileName(
-      this, tr( "Open CSV Network description file" ),
-      _lastOpenedNetworkFileName, tr( "CSV (*.csv);; All files (*)" ), nullptr,
+      this , tr( "Open CSV Network description file" ) ,
+      _lastOpenedNetworkFileName , tr( "CSV (*.csv);; All files (*)" ) ,
+      nullptr ,
       QFileDialog::DontUseNativeDialog );
 
-    if ( !pathNetwork.isEmpty() )
+    if ( !pathNetwork.isEmpty( ))
     {
       QString pathActivity = QFileDialog::getOpenFileName(
-        this, tr( "Open CSV Activity file" ), _lastOpenedNetworkFileName,
-        tr( "CSV (*.csv);; All files (*)" ), nullptr,
+        this , tr( "Open CSV Activity file" ) , _lastOpenedNetworkFileName ,
+        tr( "CSV (*.csv);; All files (*)" ) , nullptr ,
         QFileDialog::DontUseNativeDialog );
 
-      if ( !pathActivity.isEmpty( ) )
+      if ( !pathActivity.isEmpty( ))
       {
         _lastOpenedNetworkFileName = QFileInfo( pathNetwork ).path( );
         _lastOpenedActivityFileName = QFileInfo( pathActivity ).path( );
         const auto networkFile = pathNetwork.toStdString( );
         const auto activityFile = pathActivity.toStdString( );
 
-        loadData(simil::TCSV, networkFile, activityFile, simil::TSimSpikes);
+        loadData( simil::TCSV , networkFile , activityFile ,
+                  simil::TSimSpikes );
       }
     }
   }
@@ -469,27 +494,29 @@ namespace visimpl
   void MainWindow::openHDF5ThroughDialog( void )
   {
     auto path = QFileDialog::getOpenFileName(
-      this, tr( "Open a H5 network file" ), _lastOpenedNetworkFileName,
-      tr( "hdf5 ( *.h5);; All files (*)" ), nullptr,
+      this , tr( "Open a H5 network file" ) , _lastOpenedNetworkFileName ,
+      tr( "hdf5 ( *.h5);; All files (*)" ) , nullptr ,
       QFileDialog::DontUseNativeDialog );
 
-    if ( path.isEmpty() ) return;
+    if ( path.isEmpty( )) return;
 
     const auto networkFile = path.toStdString( );
 
     path =
-      QFileDialog::getOpenFileName( this, tr( "Open a H5 activity file" ), path,
-                                    tr( "hdf5 ( *.h5);; All files (*)" ),
-                                    nullptr, QFileDialog::DontUseNativeDialog );
+      QFileDialog::getOpenFileName( this , tr( "Open a H5 activity file" ) ,
+                                    path ,
+                                    tr( "hdf5 ( *.h5);; All files (*)" ) ,
+                                    nullptr ,
+                                    QFileDialog::DontUseNativeDialog );
 
-    if ( path.isEmpty() ) return;
+    if ( path.isEmpty( )) return;
 
     const auto activityFile = path.toStdString( );
 
-    loadData(simil::THDF5, networkFile, activityFile, simil::TSimSpikes);
+    loadData( simil::THDF5 , networkFile , activityFile , simil::TSimSpikes );
   }
 
-  void MainWindow::openSubsetEventFile( const std::string& filePath,
+  void MainWindow::openSubsetEventFile( const std::string& filePath ,
                                         bool append )
   {
     if ( filePath.empty( ) || !_subsetEvents )
@@ -498,31 +525,32 @@ namespace visimpl
     if ( !append )
       _subsetEvents->clear( );
 
-    QFileInfo eventsFile{QString::fromStdString(filePath)};
-    if(!eventsFile.exists())
+    QFileInfo eventsFile{ QString::fromStdString( filePath ) };
+    if ( !eventsFile.exists( ))
       return;
 
     bool h5 = false;
     QString errorText;
     try
     {
-      if(eventsFile.suffix().toLower().compare("json") == 0)
+      if ( eventsFile.suffix( ).toLower( ).compare( "json" ) == 0 )
       {
         _subsetEvents->loadJSON( filePath );
       }
-      else if(eventsFile.suffix().toLower().compare("h5") == 0)
+      else if ( eventsFile.suffix( ).toLower( ).compare( "h5" ) == 0 )
       {
         _subsetEvents->loadH5( filePath );
         h5 = true;
       }
       else
       {
-        errorText = tr("Events file not supported: %1").arg(eventsFile.absoluteFilePath());
+        errorText = tr( "Events file not supported: %1" ).arg(
+          eventsFile.absoluteFilePath( ));
       }
     }
-    catch(const std::exception &e)
+    catch ( const std::exception& e )
     {
-      errorText = QString::fromLocal8Bit(e.what());
+      errorText = QString::fromLocal8Bit( e.what( ));
     }
 
     if ( !errorText.isEmpty( ))
@@ -543,11 +571,12 @@ namespace visimpl
   void MainWindow::openSubsetEventsFileThroughDialog( void )
   {
     QString filePath = QFileDialog::getOpenFileName(
-      this, tr( "Open file containing subsets/events data" ),
-      _lastOpenedSubsetsFileName, tr( "JSON (*.json);; hdf5 ( *.h5);; All files (*)" ),
-      nullptr, QFileDialog::DontUseNativeDialog );
+      this , tr( "Open file containing subsets/events data" ) ,
+      _lastOpenedSubsetsFileName ,
+      tr( "JSON (*.json);; hdf5 ( *.h5);; All files (*)" ) ,
+      nullptr , QFileDialog::DontUseNativeDialog );
 
-    if ( !filePath.isEmpty( ) )
+    if ( !filePath.isEmpty( ))
     {
       QFileInfo eventsFile{ filePath };
       if ( eventsFile.exists( ))
@@ -560,18 +589,20 @@ namespace visimpl
 
   void MainWindow::openRecorder( void )
   {
-    auto action = qobject_cast<QAction *>(sender());
+    auto action = qobject_cast< QAction* >( sender( ));
 
     // The button stops the recorder if found.
-    if( _recorder != nullptr )
+    if ( _recorder != nullptr )
     {
-      if(action) action->setDisabled( true );
-      const bool currentlyPlaying = (_openGLWidget && _openGLWidget->player() && _openGLWidget->player()->isPlaying());
-      if(currentlyPlaying) Pause();
+      if ( action ) action->setDisabled( true );
+      const bool currentlyPlaying = ( _openGLWidget &&
+                                      _openGLWidget->player( ) &&
+                                      _openGLWidget->player( )->isPlaying( ));
+      if ( currentlyPlaying ) Pause( );
 
-      RecorderUtils::stopAndWait(_recorder, this);
+      RecorderUtils::stopAndWait( _recorder , this );
 
-      if(currentlyPlaying) Play();
+      if ( currentlyPlaying ) Play( );
 
       // Recorder will be deleted after finishing.
       _recorder = nullptr;
@@ -585,7 +616,7 @@ namespace visimpl
     params.includeScreens = false;
     params.stabilizeFramerate = true;
 
-    if(!_ui->actionAdvancedRecorderOptions->isChecked())
+    if ( !_ui->actionAdvancedRecorderOptions->isChecked( ))
     {
       params.showWorker = false;
       params.showWidgetSourceMode = false;
@@ -595,88 +626,91 @@ namespace visimpl
     RecorderDialog dialog( nullptr , params , false );
     dialog.setWindowIcon( QIcon( ":/visimpl.png" ));
     dialog.setFixedSize( 800 , 600 );
-    if ( dialog.exec( ) == QDialog::Accepted)
+    if ( dialog.exec( ) == QDialog::Accepted )
     {
       _recorder = dialog.getRecorder( );
       connect( _recorder , SIGNAL( finished( )) ,
-               _recorder , SLOT( deleteLater( )));
+               _recorder , SLOT( deleteLater( )) );
       connect( _recorder , SIGNAL( finished( )) ,
-               this , SLOT( finishRecording( )));
+               this , SLOT( finishRecording( )) );
       connect( _openGLWidget , SIGNAL( frameSwapped( )) ,
-               _recorder , SLOT( takeFrame( )));
-      if(action) action->setChecked( true );
-    } else
+               _recorder , SLOT( takeFrame( )) );
+      if ( action ) action->setChecked( true );
+    }
+    else
     {
-      if(action) action->setChecked( false );
+      if ( action ) action->setChecked( false );
     }
   }
 
   void MainWindow::closeData( void )
   {
 #ifdef SIMIL_WITH_REST_API
-    if(m_loader && m_loader->type() == simil::TREST)
+    if ( m_loader && m_loader->type( ) == simil::TREST )
     {
-      CloseDataDialog dialog(this);
-      const auto result = dialog.exec();
+      CloseDataDialog dialog( this );
+      const auto result = dialog.exec( );
 
-      if(result == QDialog::Rejected) return;
+      if ( result == QDialog::Rejected ) return;
 
-      if(dialog.keepNetwork())
+      if ( dialog.keepNetwork( ))
       {
-        QApplication::setOverrideCursor(Qt::WaitCursor);
+        QApplication::setOverrideCursor( Qt::WaitCursor );
 
-        Stop();
+        Stop( );
 
-        _objectInspectorGB->setCheckUpdates(false);
+        _objectInspectorGB->setCheckUpdates( false );
 
-        auto rest = m_loader->RESTLoader();
-        rest->resetSpikes();
+        auto rest = m_loader->RESTLoader( );
+        rest->resetSpikes( );
 
-        _summary->UpdateHistograms();
-        _stackViz->updateHistograms();
+        _summary->UpdateHistograms( );
+        _stackViz->updateHistograms( );
 
-        _objectInspectorGB->update();
-        _objectInspectorGB->setCheckUpdates(true);
+        _objectInspectorGB->update( );
+        _objectInspectorGB->setCheckUpdates( true );
 
-        _openGLWidget->resetParticles();
-        _simSlider->setSliderPosition(0);
+        _openGLWidget->resetParticles( );
+        _simSlider->setSliderPosition( 0 );
 
-        repaint();
+        repaint( );
 
-        QApplication::processEvents();
+        QApplication::processEvents( );
 
-        QApplication::restoreOverrideCursor();
+        QApplication::restoreOverrideCursor( );
 
         return;
       }
     }
 #endif
-    QApplication::setOverrideCursor(Qt::WaitCursor);
+    QApplication::setOverrideCursor( Qt::WaitCursor );
 
-    Stop();
+    Stop( );
 
-    clearGroups();
-    clearSelection();
-    _openGLWidget->setPlayer(nullptr, simil::TDataType::TDataUndefined);
-    _stackViz->closeData();
-    _ui->actionToggleStackVizDock->setChecked(false);
-    _ui->actionToggleStackVizDock->setEnabled(false);
-    _ui->actionCloseData->setEnabled(false);
+    clearGroups( );
+    clearSelection( );
+    _openGLWidget->setPlayer( nullptr , simil::TDataType::TDataUndefined );
+    _stackViz->closeData( );
+    _selectionManager->setGIDs( TGIDSet( ));
+    _domainManager->setSelection( TGIDSet( ) , tGidPosMap( ));
+    _ui->actionToggleStackVizDock->setChecked( false );
+    _ui->actionToggleStackVizDock->setEnabled( false );
+    _ui->actionCloseData->setEnabled( false );
 
-    _objectInspectorGB->setCheckUpdates(false);
-    _objectInspectorGB->setSimPlayer(nullptr);
+    _objectInspectorGB->setCheckUpdates( false );
+    _objectInspectorGB->setSimPlayer( nullptr );
 
-    _simSlider->setSliderPosition(0);
-    _summary->clear();
-    _simulationDock->setEnabled(false);
-    _simConfigurationDock->setEnabled(false);
+    _simSlider->setSliderPosition( 0 );
+    _summary->clear( );
+    _simulationDock->setEnabled( false );
+    _simConfigurationDock->setEnabled( false );
 
     m_loader = nullptr;
 
-    _tfWidget->setColorPoints( visimpl::TTransferFunction() );
-    _tfWidget->setSizeFunction( visimpl::TSizeFunction());
+    _tfWidget->setColorPoints( visimpl::TTransferFunction( ));
+    _tfWidget->setSizeFunction( visimpl::TSizeFunction( ));
 
-    QApplication::restoreOverrideCursor();
+    QApplication::restoreOverrideCursor( );
   }
 
   void MainWindow::dialogAbout( void )
@@ -685,60 +719,62 @@ namespace visimpl
       QString( "<h2>ViSimpl</h2>" ) +
       tr( "A multi-view visual analyzer of brain simulation data. " ) + "<br>" +
       tr( "Version " ) + visimpl::Version::getString( ).c_str( ) +
-      tr( " rev (%1)<br>" ).arg( visimpl::Version::getRevision( ) ) +
+      tr( " rev (%1)<br>" ).arg( visimpl::Version::getRevision( )) +
       "<a href='https://vg-lab.es/visimpl/'>https://vg-lab.es/visimpl</a>" +
       "<h4>" + tr( "Build info:" ) + "</h4>" +
-      "<ul><li>Qt " + QT_VERSION_STR + 
+      "<ul><li>Qt " + QT_VERSION_STR +
 
-#ifdef VISIMPL_USE_GMRVLEX
+      #ifdef VISIMPL_USE_GMRVLEX
       "</li><li>GmrvLex " + GMRVLEX_REV_STRING +
-#else
+      #else
       "</li><li>GmrvLex " + tr( "support not built." ) +
-#endif
+      #endif
 
-#ifdef VISIMPL_USE_PREFR
+      #ifdef VISIMPL_USE_PREFR
       "</li><li>prefr " + PREFR_REV_STRING +
-#else
+      #else
       "</li><li>prefr " + tr( "support not built." ) +
-#endif
+      #endif
 
-#ifdef VISIMPL_USE_RETO
+      #ifdef VISIMPL_USE_RETO
       "</li><li>ReTo " + RETO_REV_STRING +
-#else
+      #else
       "</li><li>ReTo " + tr( "support not built." ) +
-#endif
+      #endif
 
-#ifdef VISIMPL_USE_SCOOP
+      #ifdef VISIMPL_USE_SCOOP
       "</li><li>Scoop " + SCOOP_REV_STRING +
-#else
+      #else
       "</li><li>Scoop " + tr( "support not built." ) +
-#endif
+      #endif
 
-#ifdef VISIMPL_USE_SIMIL
+      #ifdef VISIMPL_USE_SIMIL
       "</li><li>SimIL " + SIMIL_REV_STRING +
-#else
+      #else
       "</li><li>SimIL " + tr( "support not built." ) +
-#endif
+      #endif
 
-#ifdef VISIMPL_USE_ZEROEQ
+      #ifdef VISIMPL_USE_ZEROEQ
       "</li><li>ZeroEQ " + ZEROEQ_REV_STRING +
-#else
+      #else
       "</li><li>ZeroEQ " + tr( "support not built." ) +
-#endif
+      #endif
 
       "</li><li>AcuteRecorder " + ACUTERECORDER_REV_STRING +
 
       "</li></ul>" + "<h4>" + tr( "Developed by:" ) + "</h4>" +
       "VG-Lab / URJC / UPM"
       "<br><a href='https://vg-lab.es/'>https://vg-lab.es/</a>"
-      "<br>(C) 2015-" + QString::number(QDateTime::currentDateTime().date().year()) + "<br><br>"
+      "<br>(C) 2015-" +
+      QString::number( QDateTime::currentDateTime( ).date( ).year( )) +
+      "<br><br>"
       "<a href='https://vg-lab.es'><img src=':/icons/logoVGLab.png'/></a>"
       "&nbsp;&nbsp;&nbsp;&nbsp;"
       "<a href='https://www.urjc.es'><img src=':/icons/logoURJC.png' /></a>"
       "&nbsp;&nbsp;&nbsp;&nbsp;"
       "<a href='https://www.upm.es'><img src=':/icons/logoUPM.png' /></a>";
 
-    QMessageBox::about( this, tr( "About ViSimpl" ), msj );
+    QMessageBox::about( this , tr( "About ViSimpl" ) , msj );
   }
 
   void MainWindow::dialogSelectionManagement( void )
@@ -755,15 +791,15 @@ namespace visimpl
       return;
 
     _subsetImporter->reload( _subsetEvents );
-    if(QDialog::Accepted == _subsetImporter->exec())
+    if ( QDialog::Accepted == _subsetImporter->exec( ))
     {
-      importVisualGroups();
+      importVisualGroups( );
     }
   }
 
   void MainWindow::togglePlaybackDock( void )
   {
-    if ( _ui->actionTogglePlaybackDock->isChecked( ) )
+    if ( _ui->actionTogglePlaybackDock->isChecked( ))
       _simulationDock->show( );
     else
       _simulationDock->close( );
@@ -810,20 +846,23 @@ namespace visimpl
     try
     {
       const auto eventMgr = _openGLWidget->player( )->zeqEvents( );
-      if(eventMgr)
+      if ( eventMgr )
       {
-        eventMgr->playbackOpReceived.connect( boost::bind( &MainWindow::ApplyPlaybackOperation, this, _1 ) );
-        eventMgr->frameReceived.connect( boost::bind( &MainWindow::requestPlayAt, this, _1 ) );
+        eventMgr->playbackOpReceived.connect(
+          boost::bind( &MainWindow::ApplyPlaybackOperation , this , _1 ));
+        eventMgr->frameReceived.connect(
+          boost::bind( &MainWindow::requestPlayAt , this , _1 ));
       }
     }
-    catch(std::exception &e)
+    catch ( std::exception& e )
     {
       std::cerr << "Exception when initializing player events. ";
-      std::cerr << e.what() << " " << __FILE__ << ":" << __LINE__ << std::endl;
+      std::cerr << e.what( ) << " " << __FILE__ << ":" << __LINE__ << std::endl;
     }
-    catch(...)
+    catch ( ... )
     {
-      std::cerr << "Unknown exception when initializing player events. " << __FILE__ << ":" << __LINE__ << std::endl;
+      std::cerr << "Unknown exception when initializing player events. "
+                << __FILE__ << ":" << __LINE__ << std::endl;
     }
 #endif
 
@@ -840,53 +879,60 @@ namespace visimpl
   void MainWindow::_initStackVizDock( void )
   {
     _stackVizDock = new QDockWidget( );
-    _stackVizDock->setObjectName("stackvizDock");
+    _stackVizDock->setObjectName( "stackvizDock" );
     _stackVizDock->setMinimumHeight( 100 );
     _stackVizDock->setSizePolicy( QSizePolicy::MinimumExpanding ,
                                   QSizePolicy::MinimumExpanding );
-    _stackVizDock->setVisible(false);
+    _stackVizDock->setVisible( false );
 
     _stackViz = new StackViz( this );
 
     if ( _openGLWidget && _openGLWidget->player( ))
     {
-      _stackViz->init( _openGLWidget->player( ), _openGLWidget->subsetEventsManager() );
+      _stackViz->init( _openGLWidget->player( ) ,
+                       _openGLWidget->subsetEventsManager( ));
     }
 
     _stackVizDock->setWidget( _stackViz );
     this->addDockWidget( Qt::LeftDockWidgetArea , _stackVizDock );
 
-    connect( _objectInspectorGB, SIGNAL( simDataChanged()),
-             _stackViz,          SLOT( updateHistograms()));
+    connect( _objectInspectorGB , SIGNAL( simDataChanged( )) ,
+             _stackViz , SLOT( updateHistograms( )) );
 
-    connect(_stackViz, SIGNAL(changedBins(const unsigned int)),
-            _summary, SLOT(bins(unsigned int)));
+    connect( _stackViz , SIGNAL( changedBins(
+                                   const unsigned int)) ,
+             _summary , SLOT( bins( unsigned int )) );
 
-    connect(_ui->actionStackVizShowDataManager , SIGNAL( triggered( bool )) ,
-            _stackViz , SLOT( showDisplayManagerWidget( )));
+    connect( _ui->actionStackVizShowDataManager , SIGNAL( triggered( bool )) ,
+             _stackViz , SLOT( showDisplayManagerWidget( )) );
 
-    connect(_ui->actionStackVizShowPanels , SIGNAL( triggered( bool )) ,
-            _stackViz , SLOT( showStackVizPanels(bool )));
+    connect( _ui->actionStackVizShowPanels , SIGNAL( triggered( bool )) ,
+             _stackViz , SLOT( showStackVizPanels( bool )) );
 
-    connect(_ui->actionStackVizShowDataManager , SIGNAL( triggered( bool )) ,
-            _stackViz , SLOT( showDisplayManagerWidget( )));
+    connect( _ui->actionStackVizShowDataManager , SIGNAL( triggered( bool )) ,
+             _stackViz , SLOT( showDisplayManagerWidget( )) );
 
-    connect(_ui->actionStackVizAutoNamingSelections , SIGNAL( triggered( )) ,
-            _stackViz , SLOT( toggleAutoNameSelections( )));
+    connect( _ui->actionStackVizAutoNamingSelections , SIGNAL( triggered( )) ,
+             _stackViz , SLOT( toggleAutoNameSelections( )) );
 
-    connect(_ui->actionStackVizFillPlots , SIGNAL( triggered( bool )) ,
-            _stackViz , SLOT( fillPlots( bool )));
+    connect( _ui->actionStackVizFillPlots , SIGNAL( triggered( bool )) ,
+             _stackViz , SLOT( fillPlots( bool )) );
 
-    connect(_ui->actionStackVizFocusOnPlayhead , SIGNAL( triggered( )) ,
-            _stackViz , SLOT( focusPlayback( )));
+    connect( _ui->actionStackVizFocusOnPlayhead , SIGNAL( triggered( )) ,
+             _stackViz , SLOT( focusPlayback( )) );
 
-    connect(_ui->actionStackVizFollowPlayHead , SIGNAL( triggered( bool )) ,
-            _stackViz , SLOT( followPlayhead( bool )));
+    connect( _ui->actionStackVizFollowPlayHead , SIGNAL( triggered( bool )) ,
+             _stackViz , SLOT( followPlayhead( bool )) );
 
     // this avoids making the dock smaller when the stackviz config panels
     // hide.
-    QObject::connect(_ui->actionStackVizShowPanels , &QAction::triggered ,
-            [=](bool){ this->resizeDocks({_stackVizDock}, {_stackVizDock->width()}, Qt::Horizontal);});
+    QObject::connect( _ui->actionStackVizShowPanels , &QAction::triggered ,
+                      [ = ]( bool )
+                      {
+                        this->resizeDocks( { _stackVizDock } ,
+                                           { _stackVizDock->width( ) } ,
+                                           Qt::Horizontal );
+                      } );
   }
 
   void MainWindow::_initPlaybackDock( void )
@@ -905,69 +951,73 @@ namespace visimpl
     _simSlider = new CustomSlider( Qt::Horizontal );
     _simSlider->setMinimum( 0 );
     _simSlider->setMaximum( 1000 );
-    _simSlider->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
-    _simSlider->setEnabled(false);
+    _simSlider->setSizePolicy( QSizePolicy::Preferred ,
+                               QSizePolicy::Preferred );
+    _simSlider->setEnabled( false );
 
-    _playButton = new QPushButton(_playIcon, tr(""));
-    _playButton->setSizePolicy( QSizePolicy::MinimumExpanding,
+    _playButton = new QPushButton( _playIcon , tr( "" ));
+    _playButton->setSizePolicy( QSizePolicy::MinimumExpanding ,
                                 QSizePolicy::MinimumExpanding );
-    auto stopButton = new QPushButton(QIcon(":/icons/stop.svg"), tr(""));
-    auto nextButton = new QPushButton(QIcon(":/icons/next.svg"), tr(""));
-    auto prevButton = new QPushButton(QIcon(":/icons/previous.svg"), tr(""));
+    auto stopButton = new QPushButton( QIcon( ":/icons/stop.svg" ) , tr( "" ));
+    auto nextButton = new QPushButton( QIcon( ":/icons/next.svg" ) , tr( "" ));
+    auto prevButton = new QPushButton( QIcon( ":/icons/previous.svg" ) ,
+                                       tr( "" ));
 
-    _repeatButton = new QPushButton(QIcon(":/icons/repeat.svg"), tr(""));
+    _repeatButton = new QPushButton( QIcon( ":/icons/repeat.svg" ) , tr( "" ));
     _repeatButton->setCheckable( true );
     _repeatButton->setChecked( false );
 
-    _goToButton = new QPushButton( tr("Play at...") );
+    _goToButton = new QPushButton( tr( "Play at..." ));
 
     _startTimeLabel = new QLabel( "" );
-    _startTimeLabel->setSizePolicy( QSizePolicy::MinimumExpanding,
+    _startTimeLabel->setSizePolicy( QSizePolicy::MinimumExpanding ,
                                     QSizePolicy::Preferred );
     _endTimeLabel = new QLabel( "" );
-    _endTimeLabel->setSizePolicy( QSizePolicy::Preferred,
+    _endTimeLabel->setSizePolicy( QSizePolicy::Preferred ,
                                   QSizePolicy::Preferred );
 
     unsigned int row = 2;
-    dockLayout->addWidget( _startTimeLabel, row, 0, 1, 2 );
-    dockLayout->addWidget( _simSlider, row, 1, 1, totalHSpan - 3 );
-    dockLayout->addWidget( _endTimeLabel, row, totalHSpan - 2, 1, 1,
+    dockLayout->addWidget( _startTimeLabel , row , 0 , 1 , 2 );
+    dockLayout->addWidget( _simSlider , row , 1 , 1 , totalHSpan - 3 );
+    dockLayout->addWidget( _endTimeLabel , row , totalHSpan - 2 , 1 , 1 ,
                            Qt::AlignRight );
 
     row++;
-    dockLayout->addWidget( _repeatButton, row, 7, 1, 1 );
-    dockLayout->addWidget( prevButton, row, 8, 1, 1 );
-    dockLayout->addWidget( _playButton, row, 9, 2, 2 );
-    dockLayout->addWidget( stopButton, row, 11, 1, 1 );
-    dockLayout->addWidget( nextButton, row, 12, 1, 1 );
-    dockLayout->addWidget( _goToButton, row, 13, 1, 1 );
+    dockLayout->addWidget( _repeatButton , row , 7 , 1 , 1 );
+    dockLayout->addWidget( prevButton , row , 8 , 1 , 1 );
+    dockLayout->addWidget( _playButton , row , 9 , 2 , 2 );
+    dockLayout->addWidget( stopButton , row , 11 , 1 , 1 );
+    dockLayout->addWidget( nextButton , row , 12 , 1 , 1 );
+    dockLayout->addWidget( _goToButton , row , 13 , 1 , 1 );
 
-    connect( _playButton, SIGNAL( clicked( ) ), this, SLOT( PlayPause( ) ) );
+    connect( _playButton , SIGNAL( clicked( )) , this , SLOT( PlayPause( )) );
 
-    connect( stopButton, SIGNAL( clicked( ) ), this, SLOT( Stop( ) ) );
+    connect( stopButton , SIGNAL( clicked( )) , this , SLOT( Stop( )) );
 
-    connect( nextButton, SIGNAL( clicked( ) ), this, SLOT( NextStep( ) ) );
+    connect( nextButton , SIGNAL( clicked( )) , this , SLOT( NextStep( )) );
 
-    connect( prevButton, SIGNAL( clicked( ) ), this, SLOT( PreviousStep( ) ) );
+    connect( prevButton , SIGNAL( clicked( )) , this , SLOT( PreviousStep( )) );
 
-    connect( _repeatButton, SIGNAL( clicked( ) ), this, SLOT( Repeat( ) ) );
+    connect( _repeatButton , SIGNAL( clicked( )) , this , SLOT( Repeat( )) );
 
-    connect( _simSlider, SIGNAL( sliderPressed( ) ), this, SLOT( PlayAtPosition( ) ) );
+    connect( _simSlider , SIGNAL( sliderPressed( )) , this ,
+             SLOT( PlayAtPosition( )) );
 
-    connect( _goToButton, SIGNAL( clicked( ) ), this, SLOT( playAtButtonClicked( ) ) );
+    connect( _goToButton , SIGNAL( clicked( )) , this ,
+             SLOT( playAtButtonClicked( )) );
 
-    _summary = new visimpl::Summary( nullptr, visimpl::T_STACK_FIXED );
+    _summary = new visimpl::Summary( nullptr , visimpl::T_STACK_FIXED );
     _summary->setMinimumHeight( 50 );
 
-    dockLayout->addWidget( _summary, 0, 1, 2, totalHSpan - 3 );
+    dockLayout->addWidget( _summary , 0 , 1 , 2 , totalHSpan - 3 );
 
     _simulationDock->setWidget( content );
-    this->addDockWidget(Qt::BottomDockWidgetArea, _simulationDock );
+    this->addDockWidget( Qt::BottomDockWidgetArea , _simulationDock );
 
-    connect( _summary, SIGNAL( histogramClicked( float ) ), this,
-             SLOT( PlayAtPercentage( float ) ) );
+    connect( _summary , SIGNAL( histogramClicked( float )) , this ,
+             SLOT( PlayAtPercentage( float )) );
 
-    _simulationDock->setEnabled(false);
+    _simulationDock->setEnabled( false );
   }
 
   void MainWindow::_initSimControlDock( void )
@@ -975,12 +1025,12 @@ namespace visimpl
     _simConfigurationDock = new QDockWidget( );
     _simConfigurationDock->setMinimumHeight( 100 );
     _simConfigurationDock->setMinimumWidth( 400 );
-    _simConfigurationDock->setSizePolicy( QSizePolicy::MinimumExpanding,
+    _simConfigurationDock->setSizePolicy( QSizePolicy::MinimumExpanding ,
                                           QSizePolicy::MinimumExpanding );
 
     _tfWidget = new TransferFunctionWidget( );
     _tfWidget->setMinimumHeight( 100 );
-    _tfWidget->setDialogIcon(QIcon(":/visimpl.png"));
+    _tfWidget->setDialogIcon( QIcon( ":/visimpl.png" ));
 
     _subsetImporter = new SubsetImporter( this );
     _subsetImporter->setWindowModality( Qt::WindowModal );
@@ -991,10 +1041,10 @@ namespace visimpl
     _selectionManager->setWindowModality( Qt::WindowModal );
     _selectionManager->setMinimumHeight( 300 );
     _selectionManager->setMinimumWidth( 500 );
-    _selectionManager->setWindowIcon(QIcon( ":/visimpl.png" ));
+    _selectionManager->setWindowIcon( QIcon( ":/visimpl.png" ));
 
-    connect( _selectionManager, SIGNAL( selectionChanged( void ) ), this,
-             SLOT( selectionManagerChanged( void ) ) );
+    connect( _selectionManager , SIGNAL( selectionChanged( void )) , this ,
+             SLOT( selectionManagerChanged( void )) );
 
     _deltaTimeBox = new QDoubleSpinBox( );
     _deltaTimeBox->setMinimum( 0.00000001 );
@@ -1039,7 +1089,7 @@ namespace visimpl
     _labelGID = new QLabel( "" );
     _labelPosition = new QLabel( "" );
 
-    _checkClipping = new QCheckBox( tr( "Clipping" ) );
+    _checkClipping = new QCheckBox( tr( "Clipping" ));
     _checkShowPlanes = new QCheckBox( "Show planes" );
     _buttonResetPlanes = new QPushButton( "Reset" );
     _spinBoxClippingHeight = new QDoubleSpinBox( );
@@ -1057,17 +1107,17 @@ namespace visimpl
     _spinBoxClippingDist->setMinimum( 1 );
     _spinBoxClippingDist->setMaximum( 99999 );
 
-    QColor clippingColor( 255, 255, 255, 255 );
+    QColor clippingColor( 255 , 255 , 255 , 255 );
     _frameClippingColor = new QPushButton( );
     _frameClippingColor->setStyleSheet( "background-color: " +
-                                        clippingColor.name( ) );
-    _frameClippingColor->setMinimumSize( 20, 20 );
-    _frameClippingColor->setMaximumSize( 20, 20 );
-    _frameClippingColor->setProperty(PLANES_COLOR_KEY, clippingColor.name());
+                                        clippingColor.name( ));
+    _frameClippingColor->setMinimumSize( 20 , 20 );
+    _frameClippingColor->setMaximumSize( 20 , 20 );
+    _frameClippingColor->setProperty( PLANES_COLOR_KEY , clippingColor.name( ));
 
     _buttonSelectionFromClippingPlanes = new QPushButton( "To selection" );
     _buttonSelectionFromClippingPlanes->setToolTip(
-      tr( "Create a selection set from elements between planes" ) );
+      tr( "Create a selection set from elements between planes" ));
 
     _circuitScaleX = new QDoubleSpinBox( );
     _circuitScaleX->setDecimals( 2 );
@@ -1102,13 +1152,15 @@ namespace visimpl
     QGroupBox* tSpeedGB = new QGroupBox( "Simulation playback Configuration" );
     QGridLayout* sfLayout = new QGridLayout( );
     sfLayout->setAlignment( Qt::AlignTop );
-    sfLayout->addWidget( new QLabel( "Simulation timestep:" ), 0, 0, 1, 1 );
-    sfLayout->addWidget( _deltaTimeBox, 0, 1, 1, 1 );
-    sfLayout->addWidget( new QLabel( "Timesteps per second:" ), 1, 0, 1, 1 );
-    sfLayout->addWidget( _timeStepsPSBox, 1, 1, 1, 1 );
-    sfLayout->addWidget( new QLabel( "Step playback duration (s):" ), 2, 0, 1,
+    sfLayout->addWidget( new QLabel( "Simulation timestep:" ) , 0 , 0 , 1 , 1 );
+    sfLayout->addWidget( _deltaTimeBox , 0 , 1 , 1 , 1 );
+    sfLayout->addWidget( new QLabel( "Timesteps per second:" ) , 1 , 0 , 1 ,
                          1 );
-    sfLayout->addWidget( _stepByStepDurationBox, 2, 1, 1, 1 );
+    sfLayout->addWidget( _timeStepsPSBox , 1 , 1 , 1 , 1 );
+    sfLayout->addWidget( new QLabel( "Step playback duration (s):" ) , 2 , 0 ,
+                         1 ,
+                         1 );
+    sfLayout->addWidget( _stepByStepDurationBox , 2 , 1 , 1 , 1 );
     tSpeedGB->setLayout( sfLayout );
 
     QGroupBox* scaleGB = new QGroupBox( "Scale factor (X,Y,Z)" );
@@ -1119,26 +1171,26 @@ namespace visimpl
     layoutScale->addWidget( _circuitScaleZ );
 
     QComboBox* comboShader = new QComboBox( );
-    comboShader->addItems( {"Default", "Solid"} );
+    comboShader->addItems( { "Default" , "Solid" } );
     comboShader->setCurrentIndex( 0 );
 
     QGroupBox* shaderGB = new QGroupBox( "Shader Configuration" );
     QHBoxLayout* shaderLayout = new QHBoxLayout( );
-    shaderLayout->addWidget( new QLabel( "Current shader: " ) );
+    shaderLayout->addWidget( new QLabel( "Current shader: " ));
     shaderLayout->addWidget( comboShader );
     shaderGB->setLayout( shaderLayout );
 
     QGroupBox* dFunctionGB = new QGroupBox( "Decay function" );
     QHBoxLayout* dfLayout = new QHBoxLayout( );
     dfLayout->setAlignment( Qt::AlignTop );
-    dfLayout->addWidget( new QLabel( "Decay (simulation time): " ) );
+    dfLayout->addWidget( new QLabel( "Decay (simulation time): " ));
     dfLayout->addWidget( _decayBox );
     dFunctionGB->setLayout( dfLayout );
 
     QGroupBox* rFunctionGB = new QGroupBox( "Alpha blending function" );
     QHBoxLayout* rfLayout = new QHBoxLayout( );
     rfLayout->setAlignment( Qt::AlignTop );
-    rfLayout->addWidget( new QLabel( "Alpha Blending: " ) );
+    rfLayout->addWidget( new QLabel( "Alpha Blending: " ));
     rfLayout->addWidget( _alphaNormalButton );
     rfLayout->addWidget( _alphaAccumulativeButton );
     rFunctionGB->setLayout( rfLayout );
@@ -1155,13 +1207,13 @@ namespace visimpl
 
     QPushButton* buttonSelectionManager = new QPushButton( "..." );
     buttonSelectionManager->setToolTip(
-      tr( "Show the selection management dialog" ) );
+      tr( "Show the selection management dialog" ));
     buttonSelectionManager->setMaximumWidth( 30 );
 
     QGroupBox* selFunctionGB = new QGroupBox( "Current selection" );
     QHBoxLayout* selLayout = new QHBoxLayout( );
     selLayout->setAlignment( Qt::AlignTop );
-    selLayout->addWidget( new QLabel( "Size: " ) );
+    selLayout->addWidget( new QLabel( "Size: " ));
     selLayout->addWidget( _selectionSizeLabel );
     selLayout->addWidget( buttonSelectionManager );
     selLayout->addWidget( _buttonAddGroup );
@@ -1175,19 +1227,20 @@ namespace visimpl
     QGroupBox* gbClippingPlanes = new QGroupBox( "Clipping planes" );
     QGridLayout* layoutClippingPlanes = new QGridLayout( );
     gbClippingPlanes->setLayout( layoutClippingPlanes );
-    layoutClippingPlanes->addWidget( _checkClipping, 0, 0, 1, 1 );
-    layoutClippingPlanes->addWidget( _checkShowPlanes, 0, 1, 1, 2 );
-    layoutClippingPlanes->addWidget( _buttonSelectionFromClippingPlanes, 0, 3,
-                                     1, 1 );
-    layoutClippingPlanes->addWidget( line, 1, 0, 1, 4 );
-    layoutClippingPlanes->addWidget( _frameClippingColor, 2, 0, 1, 1 );
-    layoutClippingPlanes->addWidget( _buttonResetPlanes, 2, 1, 1, 1 );
-    layoutClippingPlanes->addWidget( new QLabel( "Height" ), 2, 2, 1, 1 );
-    layoutClippingPlanes->addWidget( _spinBoxClippingHeight, 2, 3, 1, 1 );
-    layoutClippingPlanes->addWidget( new QLabel( "Distance" ), 3, 0, 1, 1 );
-    layoutClippingPlanes->addWidget( _spinBoxClippingDist, 3, 1, 1, 1 );
-    layoutClippingPlanes->addWidget( new QLabel( "Width" ), 3, 2, 1, 1 );
-    layoutClippingPlanes->addWidget( _spinBoxClippingWidth, 3, 3, 1, 1 );
+    layoutClippingPlanes->addWidget( _checkClipping , 0 , 0 , 1 , 1 );
+    layoutClippingPlanes->addWidget( _checkShowPlanes , 0 , 1 , 1 , 2 );
+    layoutClippingPlanes->addWidget( _buttonSelectionFromClippingPlanes , 0 ,
+                                     3 ,
+                                     1 , 1 );
+    layoutClippingPlanes->addWidget( line , 1 , 0 , 1 , 4 );
+    layoutClippingPlanes->addWidget( _frameClippingColor , 2 , 0 , 1 , 1 );
+    layoutClippingPlanes->addWidget( _buttonResetPlanes , 2 , 1 , 1 , 1 );
+    layoutClippingPlanes->addWidget( new QLabel( "Height" ) , 2 , 2 , 1 , 1 );
+    layoutClippingPlanes->addWidget( _spinBoxClippingHeight , 2 , 3 , 1 , 1 );
+    layoutClippingPlanes->addWidget( new QLabel( "Distance" ) , 3 , 0 , 1 , 1 );
+    layoutClippingPlanes->addWidget( _spinBoxClippingDist , 3 , 1 , 1 , 1 );
+    layoutClippingPlanes->addWidget( new QLabel( "Width" ) , 3 , 2 , 1 , 1 );
+    layoutClippingPlanes->addWidget( _spinBoxClippingWidth , 3 , 3 , 1 , 1 );
 
     QWidget* containerSelectionTools = new QWidget( );
     QVBoxLayout* layoutContainerSelection = new QVBoxLayout( );
@@ -1197,10 +1250,10 @@ namespace visimpl
     layoutContainerSelection->addWidget( gbClippingPlanes );
 
     _objectInspectorGB = new DataInspector( "Object inspector" );
-    _objectInspectorGB->addWidget( new QLabel( "GID:" ), 2, 0, 1, 1 );
-    _objectInspectorGB->addWidget( _labelGID, 2, 1, 1, 3 );
-    _objectInspectorGB->addWidget( new QLabel( "Position: " ), 3, 0, 1, 1 );
-    _objectInspectorGB->addWidget( _labelPosition, 3, 1, 1, 3 );
+    _objectInspectorGB->addWidget( new QLabel( "GID:" ) , 2 , 0 , 1 , 1 );
+    _objectInspectorGB->addWidget( _labelGID , 2 , 1 , 1 , 3 );
+    _objectInspectorGB->addWidget( new QLabel( "Position: " ) , 3 , 0 , 1 , 1 );
+    _objectInspectorGB->addWidget( _labelPosition , 3 , 1 , 1 , 3 );
 
     QGroupBox* groupBoxGroups = new QGroupBox( "Current visualization groups" );
     _groupLayout = new QVBoxLayout( );
@@ -1209,11 +1262,11 @@ namespace visimpl
     _buttonImportGroups = new QPushButton( "Import from..." );
     _buttonClearGroups = new QPushButton( "Clear" );
     _buttonClearGroups->setEnabled( false );
-    _buttonLoadGroups = new QPushButton("Load");
-    _buttonLoadGroups->setToolTip(tr("Load Groups from disk"));
-    _buttonSaveGroups = new QPushButton("Save");
-    _buttonSaveGroups->setToolTip(tr("Save Groups to disk"));
-    _buttonSaveGroups->setEnabled(false);
+    _buttonLoadGroups = new QPushButton( "Load" );
+    _buttonLoadGroups->setToolTip( tr( "Load Groups from disk" ));
+    _buttonSaveGroups = new QPushButton( "Save" );
+    _buttonSaveGroups->setToolTip( tr( "Save Groups to disk" ));
+    _buttonSaveGroups->setEnabled( false );
 
     {
       QWidget* groupContainer = new QWidget( );
@@ -1229,12 +1282,12 @@ namespace visimpl
 
       QGridLayout* groupOuterLayout = new QGridLayout( );
       groupOuterLayout->setMargin( 0 );
-      groupOuterLayout->addWidget( _buttonImportGroups, 0, 0, 1, 1 );
-      groupOuterLayout->addWidget( _buttonClearGroups, 0, 1, 1, 1 );
-      groupOuterLayout->addWidget( _buttonLoadGroups, 1, 0, 1, 1 );
-      groupOuterLayout->addWidget( _buttonSaveGroups, 1, 1, 1, 1 );
+      groupOuterLayout->addWidget( _buttonImportGroups , 0 , 0 , 1 , 1 );
+      groupOuterLayout->addWidget( _buttonClearGroups , 0 , 1 , 1 , 1 );
+      groupOuterLayout->addWidget( _buttonLoadGroups , 1 , 0 , 1 , 1 );
+      groupOuterLayout->addWidget( _buttonSaveGroups , 1 , 1 , 1 , 1 );
 
-      groupOuterLayout->addWidget( scrollGroups, 2, 0, 1, 2 );
+      groupOuterLayout->addWidget( scrollGroups , 2 , 0 , 1 , 2 );
 
       groupBoxGroups->setLayout( groupOuterLayout );
     }
@@ -1290,9 +1343,9 @@ namespace visimpl
       gbAttribGroups->setLayout( groupOuterLayout );
     }
 
-    layoutGroupAttrib->addWidget( gbAttribSel, 0, 0, 1, 2 );
-    layoutGroupAttrib->addWidget( gbAttribGroups, 0, 2, 3, 2 );
-    layoutGroupAttrib->addWidget( gbAttribStats, 1, 0, 2, 2 );
+    layoutGroupAttrib->addWidget( gbAttribSel , 0 , 0 , 1 , 2 );
+    layoutGroupAttrib->addWidget( gbAttribGroups , 0 , 2 , 3 , 2 );
+    layoutGroupAttrib->addWidget( gbAttribStats , 1 , 0 , 2 , 2 );
 
     QWidget* containerTabSelection = new QWidget( );
     QVBoxLayout* tabSelectionLayout = new QVBoxLayout( );
@@ -1310,24 +1363,24 @@ namespace visimpl
     tabAttribLayout->addWidget( _groupBoxAttrib );
 
     _modeSelectionWidget = new QTabWidget( );
-    _modeSelectionWidget->addTab( containerTabSelection, tr( "Selection" ) );
-    _modeSelectionWidget->addTab( containerTabGroups, tr( "Groups" ) );
-    _modeSelectionWidget->addTab( containerTabAttrib, tr( "Attribute" ) );
+    _modeSelectionWidget->addTab( containerTabSelection , tr( "Selection" ));
+    _modeSelectionWidget->addTab( containerTabGroups , tr( "Groups" ));
+    _modeSelectionWidget->addTab( containerTabAttrib , tr( "Attribute" ));
 
     _toolBoxOptions = new QToolBox( );
-    _toolBoxOptions->addItem( tSpeedGB, tr( "Playback Configuration" ) );
-    _toolBoxOptions->addItem( vcContainer, tr( "Visual Configuration" ) );
-    _toolBoxOptions->addItem( containerSelectionTools, tr( "Selection" ) );
-    _toolBoxOptions->addItem( _objectInspectorGB, tr( "Inspector" ));
+    _toolBoxOptions->addItem( tSpeedGB , tr( "Playback Configuration" ));
+    _toolBoxOptions->addItem( vcContainer , tr( "Visual Configuration" ));
+    _toolBoxOptions->addItem( containerSelectionTools , tr( "Selection" ));
+    _toolBoxOptions->addItem( _objectInspectorGB , tr( "Inspector" ));
 
-    connect( _objectInspectorGB, SIGNAL( simDataChanged()),
-             _openGLWidget,      SLOT( updateData()));
+    connect( _objectInspectorGB , SIGNAL( simDataChanged( )) ,
+             _openGLWidget , SLOT( updateData( )) );
 
-    connect( _objectInspectorGB, SIGNAL( simDataChanged()),
-             _summary,           SLOT( UpdateHistograms()));
+    connect( _objectInspectorGB , SIGNAL( simDataChanged( )) ,
+             _summary , SLOT( UpdateHistograms( )) );
 
-    connect (_objectInspectorGB, SIGNAL( simDataChanged()),
-             this,               SLOT(configureComponents()));
+    connect( _objectInspectorGB , SIGNAL( simDataChanged( )) ,
+             this , SLOT( configureComponents( )) );
 
     verticalLayout->setAlignment( Qt::AlignTop );
     verticalLayout->addWidget( _modeSelectionWidget );
@@ -1336,102 +1389,104 @@ namespace visimpl
     topContainer->setLayout( verticalLayout );
     _simConfigurationDock->setWidget( topContainer );
 
-    this->addDockWidget(Qt::RightDockWidgetArea, _simConfigurationDock );
+    this->addDockWidget( Qt::RightDockWidgetArea , _simConfigurationDock );
 
-    connect( _modeSelectionWidget, SIGNAL( currentChanged( int ) ),
-             _openGLWidget, SLOT( setMode( int ) ) );
+    connect( _modeSelectionWidget , SIGNAL( currentChanged( int )) ,
+             _openGLWidget , SLOT( setMode( int )) );
 
-    connect( _openGLWidget, SIGNAL( attributeStatsComputed( void ) ), this,
-             SLOT( updateAttributeStats( void ) ) );
+    connect( _openGLWidget , SIGNAL( attributeStatsComputed( void )) , this ,
+             SLOT( updateAttributeStats( void )) );
 
-    connect( _comboAttribSelection, SIGNAL( currentIndexChanged( int ) ),
-             _openGLWidget, SLOT( selectAttrib( int ) ) );
+    connect( _comboAttribSelection , SIGNAL( currentIndexChanged( int )) ,
+             _openGLWidget , SLOT( selectAttrib( int )) );
 
-    connect( comboShader, SIGNAL( currentIndexChanged( int ) ), _openGLWidget,
-             SLOT( changeShader( int ) ) );
+    connect( comboShader , SIGNAL( currentIndexChanged( int )) , _openGLWidget ,
+             SLOT( changeShader( int )) );
 
-    connect( _tfWidget, SIGNAL( colorChanged( void ) ), this,
-             SLOT( UpdateSimulationColorMapping( void ) ) );
-    connect( _tfWidget, SIGNAL( colorChanged( void ) ), this,
-             SLOT( UpdateSimulationSizeFunction( void ) ) );
-    connect( _tfWidget, SIGNAL( previewColor( void ) ), this,
-             SLOT( PreviewSimulationColorMapping( void ) ) );
-    connect( _tfWidget, SIGNAL( previewColor( void ) ), this,
-             SLOT( PreviewSimulationSizeFunction( void ) ) );
+    connect( _tfWidget , SIGNAL( colorChanged( void )) , this ,
+             SLOT( UpdateSimulationColorMapping( void )) );
+    connect( _tfWidget , SIGNAL( colorChanged( void )) , this ,
+             SLOT( UpdateSimulationSizeFunction( void )) );
+    connect( _tfWidget , SIGNAL( previewColor( void )) , this ,
+             SLOT( PreviewSimulationColorMapping( void )) );
+    connect( _tfWidget , SIGNAL( previewColor( void )) , this ,
+             SLOT( PreviewSimulationSizeFunction( void )) );
 
-    connect( buttonSelectionManager, SIGNAL( clicked( void ) ), this,
-             SLOT( dialogSelectionManagement( void ) ) );
+    connect( buttonSelectionManager , SIGNAL( clicked( void )) , this ,
+             SLOT( dialogSelectionManagement( void )) );
 
-    connect( _circuitScaleX, SIGNAL( valueChanged( double ) ), this,
-             SLOT( updateCircuitScaleValue( void ) ) );
+    connect( _circuitScaleX , SIGNAL( valueChanged( double )) , this ,
+             SLOT( updateCircuitScaleValue( void )) );
 
-    connect( _circuitScaleY, SIGNAL( valueChanged( double ) ), this,
-             SLOT( updateCircuitScaleValue( void ) ) );
+    connect( _circuitScaleY , SIGNAL( valueChanged( double )) , this ,
+             SLOT( updateCircuitScaleValue( void )) );
 
-    connect( _circuitScaleZ, SIGNAL( valueChanged( double ) ), this,
-             SLOT( updateCircuitScaleValue( void ) ) );
+    connect( _circuitScaleZ , SIGNAL( valueChanged( double )) , this ,
+             SLOT( updateCircuitScaleValue( void )) );
 
-    connect( _deltaTimeBox, SIGNAL( valueChanged( double ) ), this,
-             SLOT( updateSimDeltaTime( void ) ) );
+    connect( _deltaTimeBox , SIGNAL( valueChanged( double )) , this ,
+             SLOT( updateSimDeltaTime( void )) );
 
-    connect( _timeStepsPSBox, SIGNAL( valueChanged( double ) ), this,
-             SLOT( updateSimTimestepsPS( void ) ) );
+    connect( _timeStepsPSBox , SIGNAL( valueChanged( double )) , this ,
+             SLOT( updateSimTimestepsPS( void )) );
 
-    connect( _decayBox, SIGNAL( valueChanged( double ) ), this,
-             SLOT( updateSimulationDecayValue( void ) ) );
+    connect( _decayBox , SIGNAL( valueChanged( double )) , this ,
+             SLOT( updateSimulationDecayValue( void )) );
 
-    connect( _stepByStepDurationBox, SIGNAL( valueChanged( double ) ), this,
-             SLOT( updateSimStepByStepDuration( void ) ) );
+    connect( _stepByStepDurationBox , SIGNAL( valueChanged( double )) , this ,
+             SLOT( updateSimStepByStepDuration( void )) );
 
-    connect( _alphaNormalButton, SIGNAL( toggled( bool ) ), this,
-             SLOT( AlphaBlendingToggled( void ) ) );
+    connect( _alphaNormalButton , SIGNAL( toggled( bool )) , this ,
+             SLOT( AlphaBlendingToggled( void )) );
 
     // Clipping planes
 
     _checkClipping->setChecked( true );
-    connect( _checkClipping, SIGNAL( stateChanged( int ) ), this,
-             SLOT( clippingPlanesActive( int ) ) );
+    connect( _checkClipping , SIGNAL( stateChanged( int )) , this ,
+             SLOT( clippingPlanesActive( int )) );
     _checkClipping->setChecked( false );
 
     _checkShowPlanes->setChecked( true );
-    connect( _checkShowPlanes, SIGNAL( stateChanged( int ) ), _openGLWidget,
-             SLOT( paintClippingPlanes( int ) ) );
+    connect( _checkShowPlanes , SIGNAL( stateChanged( int )) , _openGLWidget ,
+             SLOT( paintClippingPlanes( int )) );
 
-    connect( _buttonSelectionFromClippingPlanes, SIGNAL( clicked( void ) ),
-             this, SLOT( selectionFromPlanes( void ) ) );
+    connect( _buttonSelectionFromClippingPlanes , SIGNAL( clicked( void )) ,
+             this , SLOT( selectionFromPlanes( void )) );
 
-    connect( _buttonResetPlanes, SIGNAL( clicked( void ) ), this,
-             SLOT( clippingPlanesReset( void ) ) );
+    connect( _buttonResetPlanes , SIGNAL( clicked( void )) , this ,
+             SLOT( clippingPlanesReset( void )) );
 
-    connect( _spinBoxClippingDist, SIGNAL( editingFinished( void ) ), this,
-             SLOT( spinBoxValueChanged( void ) ) );
+    connect( _spinBoxClippingDist , SIGNAL( editingFinished( void )) , this ,
+             SLOT( spinBoxValueChanged( void )) );
 
-    connect( _spinBoxClippingHeight, SIGNAL( editingFinished( void ) ), this,
-             SLOT( spinBoxValueChanged( void ) ) );
+    connect( _spinBoxClippingHeight , SIGNAL( editingFinished( void )) , this ,
+             SLOT( spinBoxValueChanged( void )) );
 
-    connect( _spinBoxClippingWidth, SIGNAL( editingFinished( void ) ), this,
-             SLOT( spinBoxValueChanged( void ) ) );
+    connect( _spinBoxClippingWidth , SIGNAL( editingFinished( void )) , this ,
+             SLOT( spinBoxValueChanged( void )) );
 
-    connect( _frameClippingColor, SIGNAL( clicked( ) ), this,
-             SLOT( colorSelectionClicked( ) ) );
+    connect( _frameClippingColor , SIGNAL( clicked( )) , this ,
+             SLOT( colorSelectionClicked( )) );
 
-    connect( _buttonClearSelection, SIGNAL( clicked( void ) ), this,
-             SLOT( clearSelection( void ) ) );
+    connect( _buttonClearSelection , SIGNAL( clicked( void )) , this ,
+             SLOT( clearSelection( void )) );
 
-    connect( _buttonAddGroup, SIGNAL( clicked( void ) ), this,
-             SLOT( addGroupFromSelection( ) ) );
+    connect( _buttonAddGroup , SIGNAL( clicked( void )) , this ,
+             SLOT( addGroupFromSelection( )) );
 
-    connect( _buttonImportGroups, SIGNAL( clicked( void ) ), this,
-             SLOT( dialogSubsetImporter( void ) ) );
+    connect( _buttonImportGroups , SIGNAL( clicked( void )) , this ,
+             SLOT( dialogSubsetImporter( void )) );
 
-    connect( _buttonClearGroups, SIGNAL( clicked( void ) ), this,
-             SLOT( clearGroups( void ) ) );
+    connect( _buttonClearGroups , SIGNAL( clicked( void )) , this ,
+             SLOT( clearGroups( void )) );
 
-    connect( _buttonLoadGroups, SIGNAL( clicked(void)), this, SLOT(loadGroups()));
-    connect( _buttonSaveGroups, SIGNAL( clicked(void)), this, SLOT(saveGroups()));
+    connect( _buttonLoadGroups , SIGNAL( clicked( void )) , this ,
+             SLOT( loadGroups( )) );
+    connect( _buttonSaveGroups , SIGNAL( clicked( void )) , this ,
+             SLOT( saveGroups( )) );
 
     _alphaNormalButton->setChecked( true );
-    _simConfigurationDock->setEnabled(false);
+    _simConfigurationDock->setEnabled( false );
   }
 
   void MainWindow::_initSummaryWidget( void )
@@ -1441,25 +1496,27 @@ namespace visimpl
     if ( simType == simil::TSimSpikes )
     {
       simil::SpikesPlayer* spikesPlayer =
-        dynamic_cast< simil::SpikesPlayer* >( _openGLWidget->player( ) );
+        dynamic_cast< simil::SpikesPlayer* >( _openGLWidget->player( ));
 
-      _summary->Init( spikesPlayer->data( ) );
+      _summary->Init( spikesPlayer->data( ));
 
-      _summary->simulationPlayer( _openGLWidget->player( ) );
-      _summary->show();
+      _summary->simulationPlayer( _openGLWidget->player( ));
+      _summary->show( );
     }
   }
 
   void MainWindow::UpdateSimulationSlider( float percentage )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
-    _startTimeLabel->setText(QString::number(_openGLWidget->currentTime(), 'f', 3));
-    _endTimeLabel->setText(QString::number(_openGLWidget->player()->endTime(), 'f', 3));
+    _startTimeLabel->setText(
+      QString::number( _openGLWidget->currentTime( ) , 'f' , 3 ));
+    _endTimeLabel->setText(
+      QString::number( _openGLWidget->player( )->endTime( ) , 'f' , 3 ));
 
     const int total = _simSlider->maximum( ) - _simSlider->minimum( );
-    const int position = (percentage * total) + _simSlider->minimum();
+    const int position = ( percentage * total ) + _simSlider->minimum( );
 
     _simSlider->setSliderPosition( position );
 
@@ -1471,54 +1528,54 @@ namespace visimpl
 
   void MainWindow::UpdateSimulationColorMapping( void )
   {
-    _openGLWidget->changeSimulationColorMapping( _tfWidget->getColors( ) );
+    _openGLWidget->changeSimulationColorMapping( _tfWidget->getColors( ));
   }
 
   void MainWindow::PreviewSimulationColorMapping( void )
   {
     _openGLWidget->changeSimulationColorMapping(
-      _tfWidget->getPreviewColors( ) );
+      _tfWidget->getPreviewColors( ));
   }
 
   void MainWindow::changeEditorColorMapping( void )
   {
-    _tfWidget->setColorPoints( _openGLWidget->getSimulationColorMapping( ) );
+    _tfWidget->setColorPoints( _openGLWidget->getSimulationColorMapping( ));
   }
 
   void MainWindow::changeEditorSizeFunction( void )
   {
-    _tfWidget->setSizeFunction( _openGLWidget->getSimulationSizeFunction( ) );
+    _tfWidget->setSizeFunction( _openGLWidget->getSimulationSizeFunction( ));
   }
 
   void MainWindow::UpdateSimulationSizeFunction( void )
   {
     _openGLWidget->changeSimulationSizeFunction(
-      _tfWidget->getSizeFunction( ) );
+      _tfWidget->getSizeFunction( ));
   }
 
   void MainWindow::PreviewSimulationSizeFunction( void )
   {
-    _openGLWidget->changeSimulationSizeFunction( _tfWidget->getSizePreview( ) );
+    _openGLWidget->changeSimulationSizeFunction( _tfWidget->getSizePreview( ));
   }
 
   void MainWindow::changeEditorSimDeltaTime( void )
   {
-    _deltaTimeBox->setValue( _openGLWidget->simulationDeltaTime( ) );
+    _deltaTimeBox->setValue( _openGLWidget->simulationDeltaTime( ));
   }
 
   void MainWindow::updateSimDeltaTime( void )
   {
-    _openGLWidget->simulationDeltaTime( _deltaTimeBox->value( ) );
+    _openGLWidget->simulationDeltaTime( _deltaTimeBox->value( ));
   }
 
   void MainWindow::changeEditorSimTimestepsPS( void )
   {
-    _timeStepsPSBox->setValue( _openGLWidget->simulationStepsPerSecond( ) );
+    _timeStepsPSBox->setValue( _openGLWidget->simulationStepsPerSecond( ));
   }
 
   void MainWindow::updateSimTimestepsPS( void )
   {
-    _openGLWidget->simulationStepsPerSecond( _timeStepsPSBox->value( ) );
+    _openGLWidget->simulationStepsPerSecond( _timeStepsPSBox->value( ));
   }
 
   void MainWindow::setCircuitSizeScaleFactor( vec3 scaleFactor )
@@ -1561,29 +1618,29 @@ namespace visimpl
 
   void MainWindow::changeEditorDecayValue( void )
   {
-    _decayBox->setValue( _openGLWidget->getSimulationDecayValue( ) );
+    _decayBox->setValue( _openGLWidget->getSimulationDecayValue( ));
   }
 
   void MainWindow::updateSimulationDecayValue( void )
   {
-    _openGLWidget->changeSimulationDecayValue( _decayBox->value( ) );
+    _openGLWidget->changeSimulationDecayValue( _decayBox->value( ));
   }
 
   void MainWindow::changeEditorStepByStepDuration( void )
   {
     _stepByStepDurationBox->setValue(
-      _openGLWidget->simulationStepByStepDuration( ) );
+      _openGLWidget->simulationStepByStepDuration( ));
   }
 
   void MainWindow::updateSimStepByStepDuration( void )
   {
     _openGLWidget->simulationStepByStepDuration(
-      _stepByStepDurationBox->value( ) );
+      _stepByStepDurationBox->value( ));
   }
 
   void MainWindow::AlphaBlendingToggled( void )
   {
-    if ( _alphaNormalButton->isChecked( ) )
+    if ( _alphaNormalButton->isChecked( ))
     {
       _openGLWidget->SetAlphaBlendingAccumulative( false );
     }
@@ -1599,54 +1656,53 @@ namespace visimpl
       return;
 
     QLayoutItem* item;
-    while ( ( item = _layoutAttribStats->takeAt( 0 ) ) )
+    while (( item = _layoutAttribStats->takeAt( 0 )))
     {
-      _layoutAttribStats->removeWidget( item->widget( ) );
+      _layoutAttribStats->removeWidget( item->widget( ));
       delete item->widget( );
     }
 
-    const auto stats = _domainManager->attributeStatistics( );
+    const auto stats = _domainManager->getAttributeClusters( );
 
-    auto insertAttribStats = [this](const tStatsGroup &stat)
+    for ( const auto& group: stats )
     {
-      const auto name = std::get< T_TYPE_NAME >( stat );
-      const auto number = std::get< T_TYPE_STATS >( stat );
-      const auto text = ( QString( name.c_str( ) ) + ": " + QString::number( number ) );
-
-      QLabel* textLabel = new QLabel( text );
-      _layoutAttribStats->addWidget( textLabel );
-    };
-    std::for_each(stats.cbegin(), stats.cend(), insertAttribStats);
+      _layoutAttribStats->addWidget( new QLabel(
+        QString::fromStdString( group.first )));
+    }
 
-    while ( ( item = _layoutAttribGroups->takeAt( 0 ) ) )
+    while (( item = _layoutAttribGroups->takeAt( 0 )))
     {
-      _layoutAttribGroups->removeWidget( item->widget( ) );
+      _layoutAttribGroups->removeWidget( item->widget( ));
       delete item->widget( );
     }
 
     _attribGroupsVisButtons.clear( );
 
     unsigned int currentIndex = 0;
-    for ( auto group : _openGLWidget->domainManager( )->attributeGroups( ) )
+    for ( const auto& entry: stats )
     {
-      QFrame* frame = new QFrame( );
-      frame->setStyleSheet( "background-color: " + group->color( ).name( ) );
-      frame->setMinimumSize( 20, 20 );
-      frame->setMaximumSize( 20, 20 );
+      auto& group = entry.second;
 
-      group->name( std::get< T_TYPE_NAME >(
-        stats[ currentIndex ] ) ); // names[ currentIndex] );
+      QFrame* frame = new QFrame( );
+      frame->setStyleSheet( "background-color: " +
+                            group->colorMapping( ).at( 0 ).second.name( ));
+      frame->setMinimumSize( 20 , 20 );
+      frame->setMaximumSize( 20 , 20 );
 
-      QCheckBox* buttonVisibility = new QCheckBox( group->name( ).c_str( ) );
+      QCheckBox* buttonVisibility = new QCheckBox( group->name( ).c_str( ));
       buttonVisibility->setChecked( true );
 
       _attribGroupsVisButtons.push_back( buttonVisibility );
 
-      connect( buttonVisibility, SIGNAL( clicked( ) ), this,
-               SLOT( checkAttributeGroupsVisibility( ) ) );
+      connect( buttonVisibility , &QCheckBox::clicked ,
+               [ group ]( bool active )
+               {
+                 group->active( active );
+               } );
 
-      _layoutAttribGroups->addWidget( frame, currentIndex, 0, 1, 1 );
-      _layoutAttribGroups->addWidget( buttonVisibility, currentIndex, 2, 1, 1 );
+      _layoutAttribGroups->addWidget( frame , currentIndex , 0 , 1 , 1 );
+      _layoutAttribGroups->addWidget( buttonVisibility , currentIndex , 2 , 1 ,
+                                      1 );
 
       ++currentIndex;
     }
@@ -1654,12 +1710,14 @@ namespace visimpl
     _layoutAttribGroups->update( );
   }
 
-  void MainWindow::updateSelectedStatsPickingSingle( unsigned int selected )
+  void MainWindow::updateSelectedStatsPickingSingle( unsigned int /*selected*/ )
   {
+    // TODO
+    /*
     auto pickingInfo = _domainManager->pickingInfoSimple( selected );
 
     _labelGID->setText(
-      QString::number( std::get< T_PART_GID >( pickingInfo ) ) );
+      QString::number( std::get< T_PART_GID >( pickingInfo )));
 
     auto position = std::get< T_PART_POSITION >( pickingInfo );
 
@@ -1669,7 +1727,9 @@ namespace visimpl
 
     _labelPosition->setText( posText );
 
-    _toolBoxOptions->setCurrentIndex( static_cast<unsigned int>( T_TOOL_Inpector ));
+    _toolBoxOptions->setCurrentIndex(
+      static_cast<unsigned int>( T_TOOL_Inpector ));
+    */
   }
 
   void MainWindow::clippingPlanesReset( void )
@@ -1681,9 +1741,9 @@ namespace visimpl
 
   void MainWindow::_resetClippingParams( void )
   {
-    _spinBoxClippingDist->setValue( _openGLWidget->clippingPlanesDistance( ) );
-    _spinBoxClippingHeight->setValue( _openGLWidget->clippingPlanesHeight( ) );
-    _spinBoxClippingWidth->setValue( _openGLWidget->clippingPlanesWidth( ) );
+    _spinBoxClippingDist->setValue( _openGLWidget->clippingPlanesDistance( ));
+    _spinBoxClippingHeight->setValue( _openGLWidget->clippingPlanesHeight( ));
+    _spinBoxClippingWidth->setValue( _openGLWidget->clippingPlanesWidth( ));
   }
 
   void MainWindow::clippingPlanesActive( int state )
@@ -1705,14 +1765,14 @@ namespace visimpl
 
   void MainWindow::spinBoxValueChanged( void )
   {
-    auto spinBox = dynamic_cast< QDoubleSpinBox* >( sender( ) );
+    auto spinBox = dynamic_cast< QDoubleSpinBox* >( sender( ));
 
     if ( spinBox == _spinBoxClippingDist )
-      _openGLWidget->clippingPlanesDistance( spinBox->value( ) );
+      _openGLWidget->clippingPlanesDistance( spinBox->value( ));
     else if ( spinBox == _spinBoxClippingHeight )
-      _openGLWidget->clippingPlanesHeight( spinBox->value( ) );
+      _openGLWidget->clippingPlanesHeight( spinBox->value( ));
     else if ( spinBox == _spinBoxClippingWidth )
-      _openGLWidget->clippingPlanesWidth( spinBox->value( ) );
+      _openGLWidget->clippingPlanesWidth( spinBox->value( ));
   }
 
   void MainWindow::showInactive( bool show )
@@ -1722,35 +1782,36 @@ namespace visimpl
 
   void MainWindow::playAtButtonClicked( void )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
     bool ok;
-    auto player = _openGLWidget->player();
+    auto player = _openGLWidget->player( );
     double result = QInputDialog::getDouble(
-      this, tr( "Set simulation time to play:" ), tr( "Simulation time" ),
-      static_cast<double>(_openGLWidget->currentTime( )),
-      static_cast<double>(player->data( )->startTime( )),
-      static_cast<double>(player->data( )->endTime( )), 3, &ok,
+      this , tr( "Set simulation time to play:" ) , tr( "Simulation time" ) ,
+      static_cast<double>(_openGLWidget->currentTime( )) ,
+      static_cast<double>(player->data( )->startTime( )) ,
+      static_cast<double>(player->data( )->endTime( )) , 3 , &ok ,
       Qt::Popup );
 
     if ( ok )
     {
-      float percentage = ( result - player->startTime( ) ) /
-                         ( player->endTime( ) - player->startTime( ) );
+      float percentage = ( result - player->startTime( )) /
+                         ( player->endTime( ) - player->startTime( ));
 
-      percentage = std::max( 0.0f, std::min( 1.0f, percentage ) );
+      percentage = std::max( 0.0f , std::min( 1.0f , percentage ));
 
-      PlayAtPercentage( percentage, true );
+      PlayAtPercentage( percentage , true );
     }
   }
 
-  bool MainWindow::_showDialog( QColor& current, const QString& message )
+  bool MainWindow::_showDialog( QColor& current , const QString& message )
   {
-    QColor result = QColorDialog::getColor( current, this, QString( message ),
+    QColor result = QColorDialog::getColor( current , this ,
+                                            QString( message ) ,
                                             QColorDialog::DontUseNativeDialog );
 
-    if ( result.isValid( ) )
+    if ( result.isValid( ))
     {
       current = result;
       return true;
@@ -1761,12 +1822,12 @@ namespace visimpl
 
   void MainWindow::colorSelectionClicked( void )
   {
-    QPushButton* button = dynamic_cast< QPushButton* >( sender( ) );
+    QPushButton* button = dynamic_cast< QPushButton* >( sender( ));
 
     if ( button == _frameClippingColor )
     {
       QColor current = _openGLWidget->clippingPlanesColor( );
-      if ( _showDialog( current, "Select planes color" ) )
+      if ( _showDialog( current , "Select planes color" ))
       {
         _openGLWidget->clippingPlanesColor( current );
       }
@@ -1779,36 +1840,37 @@ namespace visimpl
       return;
 
     auto ids = _openGLWidget->getPlanesContainedElements( );
-    visimpl::GIDUSet selectedSet( ids.begin( ), ids.end( ) );
+    visimpl::GIDUSet selectedSet( ids.begin( ) , ids.end( ));
 
-    if ( selectedSet.empty( ) )
+    if ( selectedSet.empty( ))
       return;
 
-    setSelection( selectedSet, SRC_PLANES );
+    setSelection( selectedSet , SRC_PLANES );
   }
 
   void MainWindow::selectionManagerChanged( void )
   {
-    setSelection( _selectionManager->selected( ), SRC_WIDGET );
+    setSelection( _selectionManager->selected( ) , SRC_WIDGET );
   }
 
   void MainWindow::_updateSelectionGUI( void )
   {
-    auto selection = _domainManager->selection( );
+    auto selection = _domainManager->getSelectionCluster( );
 
-    _buttonAddGroup->setEnabled( !selection.empty() );
-    _buttonClearSelection->setEnabled( !selection.empty() );
-    _selectionSizeLabel->setText( QString::number( selection.size( ) ) );
+    _buttonAddGroup->setEnabled( selection->size( ) != 0 );
+    _buttonClearSelection->setEnabled( selection->size( ) != 0 );
+    _selectionSizeLabel->setText( QString::number( selection->size( )));
     _selectionSizeLabel->update( );
   }
 
-  void MainWindow::setSelection( const GIDUSet& selectedSet,
+  void MainWindow::setSelection( const GIDUSet& selectedSet ,
                                  TSelectionSource source_ )
   {
     if ( source_ == SRC_UNDEFINED )
       return;
 
-    _domainManager->selection( selectedSet );
+    _domainManager->setSelection( selectedSet ,
+                                  _openGLWidget->getGidPositions( ));
     _openGLWidget->setSelectedGIDs( selectedSet );
 
     if ( source_ != SRC_WIDGET )
@@ -1821,7 +1883,8 @@ namespace visimpl
   {
     if ( _openGLWidget )
     {
-      _domainManager->clearSelection( );
+      _domainManager->setSelection( _openGLWidget->player( )->gids( ) ,
+                                    _openGLWidget->getGidPositions( ));
       _openGLWidget->clearSelection( );
       _selectionManager->clearSelection( );
 
@@ -1838,7 +1901,7 @@ namespace visimpl
   void MainWindow::ApplyPlaybackOperation( unsigned int playbackOp )
   {
     zeroeq::gmrv::PlaybackOperation operation =
-        static_cast<zeroeq::gmrv::PlaybackOperation>(playbackOp);
+      static_cast<zeroeq::gmrv::PlaybackOperation>(playbackOp);
 
     switch ( operation )
     {
@@ -1876,107 +1939,116 @@ namespace visimpl
 
 #endif
 
-  void MainWindow::_onSelectionEvent( lexis::data::ConstSelectedIDsPtr selected )
+  void
+  MainWindow::_onSelectionEvent( lexis::data::ConstSelectedIDsPtr selected )
   {
     if ( _openGLWidget )
     {
       std::vector< uint32_t > ids = selected->getIdsVector( );
 
-      visimpl::GIDUSet selectedSet( ids.begin( ), ids.end( ) );
+      visimpl::GIDUSet selectedSet( ids.begin( ) , ids.end( ));
 
-      setSelection( selectedSet, SRC_EXTERNAL );
+      setSelection( selectedSet , SRC_EXTERNAL );
 
-      if(_ui->actionAddZeroEQhistograms->isChecked())
+      if ( _ui->actionAddZeroEQhistograms->isChecked( ))
       {
-        addGroupFromSelection();
+        addGroupFromSelection( );
       }
     }
   }
 
 #endif
 
-  void MainWindow::addGroupControls( VisualGroup *group,
-                                     unsigned int currentIndex,
+  void MainWindow::addGroupControls( std::shared_ptr< VisualGroup > group ,
+                                     unsigned int currentIndex ,
                                      unsigned int size )
   {
     QWidget* container = new QWidget( );
-    auto itemLayout = new QHBoxLayout(container);
+    auto itemLayout = new QHBoxLayout( container );
     container->setLayout( itemLayout );
+    container->setProperty( GROUP_NAME ,
+                            QString::fromStdString( group->name( )));
 
     const auto colors = _openGLWidget->colorPalette( ).colors( );
-    currentIndex = currentIndex % colors.size();
-    auto color = colors[currentIndex].toRgb();
-    const auto variations = DomainManager::generateColorPair(color);
+    const auto paletteIdx = currentIndex % colors.size( );
+    const auto color = colors[ paletteIdx ].toRgb( );
+    const auto variations = generateColorPair( color );
 
     TTransferFunction colorVariation;
-    colorVariation.push_back( std::make_pair( 0.0f, variations.first ));
-    colorVariation.push_back( std::make_pair( 1.0f, variations.second ));
-    group->colorMapping(colorVariation);
+    colorVariation.push_back( std::make_pair( 0.0f , variations.first ));
+    colorVariation.push_back( std::make_pair( 1.0f , variations.second ));
+    group->colorMapping( colorVariation );
 
-    auto tfWidget = new TransferFunctionWidget(container);
-    tfWidget->setColorPoints(group->colorMapping());
-    tfWidget->setSizeFunction(group->sizeFunction());
-    tfWidget->setDialogIcon(QIcon(":/visimpl.png"));
-    tfWidget->setProperty(GROUP_KEY, static_cast<unsigned int>(currentIndex));
+    auto tfWidget = new TransferFunctionWidget( container );
+    tfWidget->setColorPoints( group->colorMapping( ));
+    tfWidget->setSizeFunction( group->sizeFunction( ));
+    tfWidget->setDialogIcon( QIcon( ":/visimpl.png" ));
+    tfWidget->setProperty( GROUP_NAME ,
+                           QString::fromStdString( group->name( )));
 
-    itemLayout->addWidget(tfWidget);
+    itemLayout->addWidget( tfWidget );
 
-    const auto presetName = QString("Group selection %1").arg(currentIndex);
+    const auto presetName = QString( "Group selection %1" ).arg( currentIndex );
     QGradientStops stops;
-    stops << qMakePair( 0.0,  variations.first)
-          << qMakePair( 1.0,  variations.second);
-    tfWidget->addPreset(TransferFunctionWidget::Preset(presetName, stops));
+    stops << qMakePair( 0.0 , variations.first )
+          << qMakePair( 1.0 , variations.second );
+    tfWidget->addPreset( TransferFunctionWidget::Preset( presetName , stops ));
 
-    connect( tfWidget, SIGNAL(colorChanged()),
-             this,     SLOT(onGroupColorChanged()));
-    connect( tfWidget, SIGNAL(previewColor()),
-             this,     SLOT(onGroupPreview()));
+    connect( tfWidget , SIGNAL( colorChanged( )) ,
+             this , SLOT( onGroupColorChanged( )) );
+    connect( tfWidget , SIGNAL( previewColor( )) ,
+             this , SLOT( onGroupPreview( )) );
 
     QCheckBox* visibilityCheckbox = new QCheckBox( "active" );
-    visibilityCheckbox->setChecked( group->active() );
+    visibilityCheckbox->setChecked( group->active( ));
 
-    connect( visibilityCheckbox, SIGNAL( clicked( ) ), this,
-             SLOT( checkGroupsVisibility( ) ) );
+    connect( visibilityCheckbox , SIGNAL( clicked( )) , this ,
+             SLOT( checkGroupsVisibility( )) );
 
-    QString numberText = QString( "# " ).append( QString::number( size ) );
+    QString numberText = QString( "# " ).append( QString::number( size ));
 
-    auto nameButton = new QPushButton(group->name().c_str());
-    nameButton->setFlat(true);
-    nameButton->setProperty(GROUP_KEY, static_cast<unsigned int>(currentIndex));
+    auto nameButton = new QPushButton( group->name( ).c_str( ));
+    nameButton->setFlat( true );
+    nameButton->setObjectName( "nameButton" );
+    nameButton->setProperty( GROUP_NAME ,
+                             QString::fromStdString( group->name( )));
 
-    connect(nameButton, SIGNAL(clicked()), this, SLOT(onGroupNameClicked()));
+    connect( nameButton , SIGNAL( clicked( )) , this ,
+             SLOT( onGroupNameClicked( )) );
 
-    auto deleteButton = new QPushButton(QIcon(":/icons/close.svg"), "");
-    deleteButton->setProperty(GROUP_POINTER_KEY, reinterpret_cast<unsigned long long>(group));
+    auto deleteButton = new QPushButton( QIcon( ":/icons/close.svg" ) , "" );
+    deleteButton->setProperty( GROUP_NAME ,
+                               QString::fromStdString( group->name( )));
 
-    connect(deleteButton, SIGNAL(clicked()), this, SLOT(onGroupDeleteClicked()));
+    connect( deleteButton , SIGNAL( clicked( )) , this ,
+             SLOT( onGroupDeleteClicked( )) );
 
-    auto firstLayout = new QHBoxLayout();
-    firstLayout->setMargin(0);
-    firstLayout->addWidget(nameButton, 1);
-    firstLayout->addWidget(deleteButton, 0);
+    auto firstLayout = new QHBoxLayout( );
+    firstLayout->setMargin( 0 );
+    firstLayout->addWidget( nameButton , 1 );
+    firstLayout->addWidget( deleteButton , 0 );
 
-    auto layout = new QVBoxLayout();
-    layout->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
-    layout->addLayout(firstLayout);
+    auto layout = new QVBoxLayout( );
+    layout->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+    layout->addLayout( firstLayout );
     layout->addWidget( visibilityCheckbox );
-    layout->addWidget( new QLabel( numberText ) );
+    layout->addWidget( new QLabel( numberText ));
 
-    itemLayout->insertLayout(1, layout, 0);
-    itemLayout->setSizeConstraint(QLayout::SizeConstraint::SetMinimumSize);
+    itemLayout->insertLayout( 1 , layout , 0 );
+    itemLayout->setSizeConstraint( QLayout::SizeConstraint::SetMinimumSize );
 
     _groupsVisButtons.push_back(
-      std::make_tuple( container, visibilityCheckbox ) );
+      std::make_tuple( container , visibilityCheckbox ));
 
     _groupLayout->addWidget( container );
 
     _buttonClearGroups->setEnabled( true );
-    _buttonSaveGroups->setEnabled(true);
+    _buttonSaveGroups->setEnabled( true );
   }
 
   void MainWindow::Stop( bool notify )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
     if ( _openGLWidget )
@@ -1984,7 +2056,7 @@ namespace visimpl
       _openGLWidget->Stop( );
       _playButton->setIcon( _playIcon );
       _startTimeLabel->setText(
-        QString::number(_openGLWidget->player()->startTime(),'f',3));
+        QString::number( _openGLWidget->player( )->startTime( ) , 'f' , 3 ));
 
       _openGLWidget->playbackMode( TPlaybackMode::CONTINUOUS );
 
@@ -1997,55 +2069,62 @@ namespace visimpl
     }
   }
 
-void MainWindow::clearGroups( void )
+  void MainWindow::clearGroups( void )
   {
-    while(!_groupsVisButtons.empty())
-      removeVisualGroup(0);
+    while ( !_groupsVisButtons.empty( ))
+    {
+      auto container = std::get< 0 >( _groupsVisButtons.at( 0 ));
+      auto groupName = container->property( GROUP_NAME ).toString( );
+
+      removeVisualGroup( groupName );
+    }
   }
 
   void MainWindow::importVisualGroups( void )
   {
     const auto& groups = _subsetImporter->selectedSubsets( );
 
-    const auto& allGIDs = _domainManager->gids( );
+    const auto& allGIDs = _openGLWidget->player( )->gids( );
 
-    auto addGroup = [this, &allGIDs](const std::string &groupName)
+    auto addGroup = [ this , &allGIDs ]( const std::string& groupName )
     {
       const auto subset = _subsetEvents->getSubset( groupName );
 
       GIDUSet filteredGIDs;
-      auto filterGIDs = [&filteredGIDs, &allGIDs](const uint32_t gid)
+      auto filterGIDs = [ &filteredGIDs , &allGIDs ]( const uint32_t gid )
       {
-        if ( allGIDs.find( gid ) != allGIDs.end( ) )
+        if ( allGIDs.find( gid ) != allGIDs.end( ))
           filteredGIDs.insert( gid );
       };
-      std::for_each(subset.cbegin(), subset.cend(), filterGIDs);
+      std::for_each( subset.cbegin( ) , subset.cend( ) , filterGIDs );
 
-      const auto group = _domainManager->addVisualGroup( filteredGIDs, groupName );
+      _openGLWidget->makeCurrent( );
+      const auto group = _domainManager->createGroup(
+        filteredGIDs , _openGLWidget->getGidPositions( ) , groupName );
 
-      addGroupControls( group, _domainManager->groups( ).size( ) - 1,
-                        filteredGIDs.size( ) );
+      addGroupControls( group , _domainManager->getGroupAmount( ) - 1 ,
+                        filteredGIDs.size( ));
 
       visimpl::Selection selection;
       selection.name = groupName;
       selection.gids = filteredGIDs;
       _stackViz->addSelection( selection );
     };
-    std::for_each(groups.cbegin(), groups.cend(), addGroup);
+    std::for_each( groups.cbegin( ) , groups.cend( ) , addGroup );
 
-    _openGLWidget->setUpdateGroups( );
-    _openGLWidget->subsetEventsManager(_subsetEvents);
-    _openGLWidget->showEventsActivityLabels(_ui->actionShowEventsActivity->isChecked());
+    _openGLWidget->subsetEventsManager( _subsetEvents );
+    _openGLWidget->showEventsActivityLabels(
+      _ui->actionShowEventsActivity->isChecked( ));
 
-    _buttonImportGroups->setEnabled( groups.empty() );
-    _buttonClearGroups->setEnabled( !groups.empty() );
+    _buttonImportGroups->setEnabled( groups.empty( ));
+    _buttonClearGroups->setEnabled( !groups.empty( ));
   }
 
   void MainWindow::addGroupFromSelection( void )
   {
-    const unsigned int currentIndex = _domainManager->groups( ).size( );
+    const unsigned int currentIndex = _domainManager->getGroupAmount( );
 
-    QString groupName = QString( "Group " + QString::number( currentIndex ) );
+    QString groupName = QString( "Group " + QString::number( currentIndex ));
     if ( !_autoNameGroups )
     {
       bool ok;
@@ -2057,19 +2136,22 @@ void MainWindow::clearGroups( void )
       if ( !ok ) return;
     }
 
-    const auto group = _domainManager->addVisualGroupFromSelection(
+    _openGLWidget->makeCurrent( );
+    const auto group = _domainManager->createGroupFromSelection(
+      _openGLWidget->getGidPositions( ) ,
       groupName.toStdString( ));
 
     addGroupControls( group ,
-                      _domainManager->groups( ).size( ) - 1 ,
-                      _domainManager->selection( ).size( ));
+                      _domainManager->getGroupAmount( ) - 1 ,
+                      _domainManager->getSelectionCluster( )->size( ));
 
-    _openGLWidget->setUpdateGroups( );
     _openGLWidget->update( );
 
-
     visimpl::Selection selection;
-    selection.gids = _domainManager->selection( );
+
+    for ( const auto& item: group->getGids( ))
+      selection.gids.insert( item );
+
     selection.name = groupName.toStdString( );
 
     _stackViz->addSelection( selection );
@@ -2078,38 +2160,21 @@ void MainWindow::clearGroups( void )
   void MainWindow::checkGroupsVisibility( void )
   {
     unsigned int counter = 0;
-    auto group = _openGLWidget->domainManager( )->groups( ).begin( );
-    for ( auto button : _groupsVisButtons )
+    for ( auto button: _groupsVisButtons )
     {
+      auto container = std::get< gr_container >( button );
       auto checkBox = std::get< gr_checkbox >( button );
+      auto name = container->property( GROUP_NAME )
+        .toString( ).toStdString( );
+      auto group = _openGLWidget->domainManager( )->getGroup( name );
 
-      if ( checkBox->isChecked( ) != ( *group )->active( ) )
+      if ( checkBox->isChecked( ) != group->active( ))
       {
         const auto state = checkBox->isChecked( );
-        _domainManager->setVisualGroupState( counter , state );
+        group->active( state );
         _stackViz->setHistogramVisible( counter , state );
       }
 
-      ++group;
-      ++counter;
-    }
-
-    _openGLWidget->setUpdateGroups( );
-    _openGLWidget->update( );
-  }
-
-  void MainWindow::checkAttributeGroupsVisibility( void )
-  {
-    unsigned int counter = 0;
-    auto group = _openGLWidget->domainManager( )->attributeGroups( ).begin( );
-    for ( auto button : _attribGroupsVisButtons )
-    {
-      if ( button->isChecked( ) != ( *group )->active( ) )
-      {
-        _openGLWidget->domainManager( )->setVisualGroupState(
-          counter, button->isChecked( ), true );
-      }
-      ++group;
       ++counter;
     }
 
@@ -2118,10 +2183,10 @@ void MainWindow::clearGroups( void )
 
   void MainWindow::PlayPause( bool notify )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
-    if ( !_openGLWidget->player( )->isPlaying( ) )
+    if ( !_openGLWidget->player( )->isPlaying( ))
       Play( notify );
     else
       Pause( notify );
@@ -2129,7 +2194,7 @@ void MainWindow::clearGroups( void )
 
   void MainWindow::Play( bool notify )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
     if ( _openGLWidget )
@@ -2139,7 +2204,7 @@ void MainWindow::clearGroups( void )
       _playButton->setIcon( _pauseIcon );
 
       if ( _openGLWidget->playbackMode( ) == TPlaybackMode::STEP_BY_STEP &&
-           _openGLWidget->completedStep( ) )
+           _openGLWidget->completedStep( ))
         _openGLWidget->playbackMode( TPlaybackMode::CONTINUOUS );
 
       if ( notify )
@@ -2153,7 +2218,7 @@ void MainWindow::clearGroups( void )
 
   void MainWindow::Pause( bool notify )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
     if ( _openGLWidget )
@@ -2161,7 +2226,7 @@ void MainWindow::clearGroups( void )
       _openGLWidget->Pause( );
       _playButton->setIcon( _playIcon );
       _startTimeLabel->setText(
-          QString::number(_openGLWidget->player()->currentTime(), 'f',3));
+        QString::number( _openGLWidget->player( )->currentTime( ) , 'f' , 3 ));
 
       if ( notify )
       {
@@ -2174,7 +2239,7 @@ void MainWindow::clearGroups( void )
 
   void MainWindow::Repeat( bool notify )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
     if ( _openGLWidget )
@@ -2185,7 +2250,8 @@ void MainWindow::clearGroups( void )
       if ( notify )
       {
 #ifdef VISIMPL_USE_GMRVLEX
-        const auto op = repeat ? zeroeq::gmrv::ENABLE_LOOP : zeroeq::gmrv::DISABLE_LOOP;
+        const auto op = repeat ? zeroeq::gmrv::ENABLE_LOOP
+                               : zeroeq::gmrv::DISABLE_LOOP;
         sendZeroEQPlaybackOperation( op );
 #endif
       }
@@ -2194,68 +2260,70 @@ void MainWindow::clearGroups( void )
 
   void MainWindow::requestPlayAt( float timePos )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
-    auto player = _openGLWidget->player();
-    const auto tBegin = player->startTime();
-    const auto tEnd   = player->endTime();
-    const auto newPosition = std::min(tEnd, std::max(tBegin, timePos));
-    const auto isOverflow = std::abs(timePos-newPosition) > std::numeric_limits<float>::epsilon();
+    auto player = _openGLWidget->player( );
+    const auto tBegin = player->startTime( );
+    const auto tEnd = player->endTime( );
+    const auto newPosition = std::min( tEnd , std::max( tBegin , timePos ));
+    const auto isOverflow = std::abs( timePos - newPosition ) >
+                            std::numeric_limits< float >::epsilon( );
 
-    PlayAtTime( newPosition, isOverflow );
+    PlayAtTime( newPosition , isOverflow );
 
-    if(isOverflow)
-      Pause(true);
+    if ( isOverflow )
+      Pause( true );
   }
 
   void MainWindow::PlayAtPosition( bool notify )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
-    PlayAtPosition( _simSlider->sliderPosition( ), notify );
+    PlayAtPosition( _simSlider->sliderPosition( ) , notify );
   }
 
-  void MainWindow::PlayAtPosition( int sliderPosition, bool notify )
+  void MainWindow::PlayAtPosition( int sliderPosition , bool notify )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
-    const int sMin = _simSlider->minimum();
-    const int sMax = _simSlider->maximum();
-    const float percentage = static_cast<float>(sliderPosition - sMin) * (sMax - sMin);
+    const int sMin = _simSlider->minimum( );
+    const int sMax = _simSlider->maximum( );
+    const float percentage =
+      static_cast<float>(sliderPosition - sMin) * ( sMax - sMin );
 
-    PlayAtPercentage(percentage, notify);
+    PlayAtPercentage( percentage , notify );
   }
 
-  void MainWindow::PlayAtPercentage( float percentage, bool notify )
+  void MainWindow::PlayAtPercentage( float percentage , bool notify )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
-    auto player = _openGLWidget->player();
-    const auto tBegin = player->startTime();
-    const auto tEnd = player->endTime();
-    const auto timePos = (percentage * (tEnd - tBegin)) + tBegin;
+    auto player = _openGLWidget->player( );
+    const auto tBegin = player->startTime( );
+    const auto tEnd = player->endTime( );
+    const auto timePos = ( percentage * ( tEnd - tBegin )) + tBegin;
 
-    PlayAtTime(timePos, notify);
+    PlayAtTime( timePos , notify );
   }
 
-  void MainWindow::PlayAtTime(float timePos, bool notify)
+  void MainWindow::PlayAtTime( float timePos , bool notify )
   {
-    if(!_openGLWidget || !_openGLWidget->player())
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
-    auto player = _openGLWidget->player();
-    const auto tBegin = player->startTime();
-    const auto tEnd = player->endTime();
-    const auto newPosition = std::max(tBegin, std::min(tEnd, timePos));
-    const auto percentage = (newPosition - tBegin) / (tEnd - tBegin);
+    auto player = _openGLWidget->player( );
+    const auto tBegin = player->startTime( );
+    const auto tEnd = player->endTime( );
+    const auto newPosition = std::max( tBegin , std::min( tEnd , timePos ));
+    const auto percentage = ( newPosition - tBegin ) / ( tEnd - tBegin );
 
-    const auto sMin = _simSlider->minimum();
-    const auto sMax = _simSlider->maximum();
-    const int sliderPosition = (percentage * (sMax - sMin)) + sMin;
+    const auto sMin = _simSlider->minimum( );
+    const auto sMax = _simSlider->maximum( );
+    const int sliderPosition = ( percentage * ( sMax - sMin )) + sMin;
 
     _simSlider->setSliderPosition( sliderPosition );
 
@@ -2263,7 +2331,8 @@ void MainWindow::clearGroups( void )
 
     _openGLWidget->PlayAt( newPosition );
     _openGLWidget->playbackMode( TPlaybackMode::CONTINUOUS );
-    _startTimeLabel->setText(QString::number(player->currentTime(), 'f',3));
+    _startTimeLabel->setText(
+      QString::number( player->currentTime( ) , 'f' , 3 ));
 
     if ( notify )
     {
@@ -2272,29 +2341,33 @@ void MainWindow::clearGroups( void )
       {
         // Send event
         auto eventMgr = player->zeqEvents( );
-        if(eventMgr)
+        if ( eventMgr )
         {
-          eventMgr->sendFrame( player->startTime(), player->endTime(), player->currentTime());
+          eventMgr->sendFrame( player->startTime( ) , player->endTime( ) ,
+                               player->currentTime( ));
         }
       }
-      catch(const std::exception &e)
+      catch ( const std::exception& e )
       {
-        std::cerr << "Exception when sending frame. " << e.what() << __FILE__ << ":" << __LINE__ << std::endl;
+        std::cerr << "Exception when sending frame. " << e.what( ) << __FILE__
+                  << ":" << __LINE__ << std::endl;
       }
-      catch(...)
+      catch ( ... )
       {
-        std::cerr << "Unknown exception when sending frame. " << __FILE__ << ":" << __LINE__  << std::endl;
+        std::cerr << "Unknown exception when sending frame. " << __FILE__ << ":"
+                  << __LINE__ << std::endl;
       }
 #endif
 #ifdef VISIMPL_USE_GMRVLEX
-      sendZeroEQPlaybackOperation(zeroeq::gmrv::PLAY);
+      sendZeroEQPlaybackOperation( zeroeq::gmrv::PLAY );
 #endif
     }
 
   }
+
   void MainWindow::PreviousStep( bool /*notify*/ )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
     _playButton->setIcon( _pauseIcon );
@@ -2304,7 +2377,7 @@ void MainWindow::clearGroups( void )
 
   void MainWindow::NextStep( bool /*notify*/ )
   {
-    if ( !_openGLWidget || !_openGLWidget->player( ) )
+    if ( !_openGLWidget || !_openGLWidget->player( ))
       return;
 
     _playButton->setIcon( _pauseIcon );
@@ -2320,55 +2393,55 @@ void MainWindow::clearGroups( void )
     }
   }
 
-  void MainWindow::onGroupColorChanged()
+  void MainWindow::onGroupColorChanged( )
   {
-    auto tfw = qobject_cast<TransferFunctionWidget *>(sender());
-    if(tfw)
+    auto tfw = qobject_cast< TransferFunctionWidget* >( sender( ));
+    if ( tfw )
     {
-      bool ok = false;
-      size_t groupNum = tfw->property(GROUP_KEY).toUInt(&ok);
-
-      if(!ok) return;
-      updateGroupColors(groupNum, tfw->getColors(), tfw->getSizeFunction());
+      auto groupName = tfw->property( GROUP_NAME ).toString( );
+      updateGroupColors( groupName.toStdString( ) , tfw->getColors( ) ,
+                         tfw->getSizeFunction( ));
     }
   }
 
-  void MainWindow::onGroupPreview()
+  void MainWindow::onGroupPreview( )
   {
-    auto tfw = qobject_cast<TransferFunctionWidget *>(sender());
-    if(tfw)
+    auto tfw = qobject_cast< TransferFunctionWidget* >( sender( ));
+    if ( tfw )
     {
       bool ok = false;
-      size_t groupNum = tfw->property(GROUP_KEY).toUInt(&ok);
+      auto groupName = tfw->property( GROUP_NAME ).toString( );
 
-      if(!ok) return;
-      updateGroupColors(groupNum, tfw->getPreviewColors(), tfw->getSizePreview());
+      if ( !ok ) return;
+      updateGroupColors( groupName.toStdString( ) , tfw->getPreviewColors( ) ,
+                         tfw->getSizePreview( ));
     }
   }
 
-  void MainWindow::updateGroupColors(size_t idx, const TTransferFunction &t,
-      const TSizeFunction &s)
+  void
+  MainWindow::updateGroupColors( std::string name , const TTransferFunction& t ,
+                                 const TSizeFunction& s )
   {
-    const auto groups = _domainManager->groups();
-    const auto groupNum = std::min(idx, groups.size() - 1);
-    groups[groupNum]->colorMapping(t);
-    groups[groupNum]->sizeFunction(s);
+    const auto& groups = _domainManager->getGroups( );
+    groups.at( name )->colorMapping( t );
+    groups.at( name )->sizeFunction( s );
   }
 
-  void MainWindow::loadData(const simil::TDataType type,
-                            const std::string arg_1, const std::string arg_2,
-                            const simil::TSimulationType simType, const std::string &subsetEventFile)
+  void MainWindow::loadData( const simil::TDataType type ,
+                             const std::string arg_1 , const std::string arg_2 ,
+                             const simil::TSimulationType simType ,
+                             const std::string& subsetEventFile )
   {
-    closeLoadingDialog();
+    closeLoadingDialog( );
 
-    Q_ASSERT(type != simil::TDataType::TREST);
+    Q_ASSERT( type != simil::TDataType::TREST );
 
-    QApplication::setOverrideCursor(Qt::WaitCursor);
+    QApplication::setOverrideCursor( Qt::WaitCursor );
 
-    _objectInspectorGB->setCheckUpdates(false);
-    _ui->actionConfigureREST->setEnabled(false);
+    _objectInspectorGB->setCheckUpdates( false );
+    _ui->actionConfigureREST->setEnabled( false );
 
-    Q_ASSERT(simType == simil::TSimulationType::TSimSpikes);
+    Q_ASSERT( simType == simil::TSimulationType::TSimSpikes );
 
     m_loaderDialog = new LoadingDialog( this );
     m_loaderDialog->show( );
@@ -2378,17 +2451,17 @@ void MainWindow::clearGroups( void )
     m_loader = std::make_shared< LoaderThread >( );
     m_loader->setData( type , arg_1 , arg_2 );
 
-    connect( m_loader.get( ) , SIGNAL( finished( )),
-             this, SLOT( onDataLoaded( )) );
-    connect( m_loader.get( ) , SIGNAL( progress( int )),
+    connect( m_loader.get( ) , SIGNAL( finished( )) ,
+             this , SLOT( onDataLoaded( )) );
+    connect( m_loader.get( ) , SIGNAL( progress( int )) ,
              m_loaderDialog , SLOT( setProgress( int )) );
     connect( m_loader.get( ) , SIGNAL( network( unsigned int )) ,
              m_loaderDialog , SLOT( setNetwork( unsigned int )) );
     connect( m_loader.get( ) , SIGNAL( spikes( unsigned int )) ,
              m_loaderDialog , SLOT( setSpikesValue( unsigned int )) );
 
-    _lastOpenedNetworkFileName = QString::fromStdString(arg_1);
-    _lastOpenedSubsetsFileName = QString::fromStdString(subsetEventFile);
+    _lastOpenedNetworkFileName = QString::fromStdString( arg_1 );
+    _lastOpenedSubsetsFileName = QString::fromStdString( subsetEventFile );
 
     m_loader->start( );
   }
@@ -2403,74 +2476,74 @@ void MainWindow::clearGroups( void )
     }
   }
 
-  void MainWindow::onDataLoaded()
+  void MainWindow::onDataLoaded( )
   {
-    if(!m_loader) return;
+    if ( !m_loader ) return;
 
-    const auto error = m_loader->errors();
-    if (!error.empty())
+    const auto error = m_loader->errors( );
+    if ( !error.empty( ))
     {
-      closeLoadingDialog();
-      QApplication::restoreOverrideCursor();
+      closeLoadingDialog( );
+      QApplication::restoreOverrideCursor( );
 
-      const auto message = QString::fromStdString(error);
-      QMessageBox::critical(this, tr("Error loading data"), message,
-          QMessageBox::Ok);
+      const auto message = QString::fromStdString( error );
+      QMessageBox::critical( this , tr( "Error loading data" ) , message ,
+                             QMessageBox::Ok );
 
       m_loader = nullptr;
       return;
     }
 
-    simil::SpikesPlayer *player = nullptr;
-    const auto dataType = m_loader->type();
+    simil::SpikesPlayer* player = nullptr;
+    const auto dataType = m_loader->type( );
 
     switch ( dataType )
     {
       case simil::TBlueConfig:
       case simil::TCSV:
       case simil::THDF5:
-        {
-          const auto spikeData = m_loader->simulationData( );
+      {
+        const auto spikeData = m_loader->simulationData( );
 
-          player = new simil::SpikesPlayer( );
-          player->LoadData( spikeData );
+        player = new simil::SpikesPlayer( );
+        player->LoadData( spikeData );
 
-          m_loader = nullptr;
-        }
+        m_loader = nullptr;
+      }
         break;
       case simil::TREST:
-        {
-          const auto netData = m_loader->network( );
-          const auto simData = m_loader->simulationData( );
+      {
+        const auto netData = m_loader->network( );
+        const auto simData = m_loader->simulationData( );
 
-          player = new simil::SpikesPlayer( );
-          player->LoadData( netData , simData );
+        player = new simil::SpikesPlayer( );
+        player->LoadData( netData , simData );
 
-          _subsetEvents = netData->subsetsEvents();
+        _subsetEvents = netData->subsetsEvents( );
 
-          // NOTE: loader doesn't get destroyed because has a loop for getting data.
-        }
+        // NOTE: loader doesn't get destroyed because has a loop for getting data.
+      }
         break;
       case simil::TDataUndefined:
       default:
-        {
-          m_loader = nullptr;
-          closeLoadingDialog( );
-          QMessageBox::critical( this , tr( "Error loading data" ) ,
-                                 tr( "Data type is undefined after loading" ) ,
-                                 QMessageBox::Ok );
+      {
+        m_loader = nullptr;
+        closeLoadingDialog( );
+        QMessageBox::critical( this , tr( "Error loading data" ) ,
+                               tr( "Data type is undefined after loading" ) ,
+                               QMessageBox::Ok );
 
-          return;
-        }
+        return;
+      }
         break;
     }
 
-    if(!player)
+    if ( !player )
     {
       closeLoadingDialog( );
       QApplication::restoreOverrideCursor( );
 
-      const auto message = tr("Unable to load data.");
+      const auto message = tr( "Unable to load data." );
       QMessageBox::critical( this , tr( "Error loading data" ) , message ,
                              QMessageBox::Ok );
 
@@ -2484,43 +2557,44 @@ void MainWindow::clearGroups( void )
       m_loaderDialog->setSpikesValue( player->spikesSize( ));
       m_loaderDialog->repaint( );
     }
-
-    _openGLWidget->setPlayer(player, dataType);
-    _modeSelectionWidget->setCurrentIndex(0);
+    _openGLWidget->setPlayer( player , dataType );
+    _modeSelectionWidget->setCurrentIndex( 0 );
 
     _openGLWidget->subsetEventsManager( _subsetEvents );
-    _openGLWidget->showEventsActivityLabels( _ui->actionShowEventsActivity->isChecked( ));
-    _openGLWidget->idleUpdate( _ui->actionUpdateOnIdle->isChecked( ) );
+    _openGLWidget->showEventsActivityLabels(
+      _ui->actionShowEventsActivity->isChecked( ));
+    _openGLWidget->idleUpdate( _ui->actionUpdateOnIdle->isChecked( ));
 
     configureComponents( );
 
-    openSubsetEventFile( m_subsetEventFile, false );
+    openSubsetEventFile( m_subsetEventFile , false );
 
     _configurePlayer( );
 
-    _comboAttribSelection->clear();
+    _comboAttribSelection->clear( );
 
-    _stackViz->init( player, _subsetEvents );
+    _stackViz->init( player , _subsetEvents );
 
-    _subsetImporter->reload(_subsetEvents);
+    _subsetImporter->reload( _subsetEvents );
 
-    switch(dataType)
+    switch ( dataType )
     {
       case simil::TDataType::TBlueConfig:
-        {
-          const QStringList attributes = {"Morphological type", "Functional type"};
-          _comboAttribSelection->addItems( attributes );
-        }
+      {
+        const QStringList attributes = { "Morphological type" ,
+                                         "Functional type" };
+        _comboAttribSelection->addItems( attributes );
+      }
         break;
       case simil::TDataType::TREST:
-        {
+      {
 #ifdef SIMIL_WITH_REST_API
-          const auto waitTime = m_loader->RESTLoader()->getConfiguration().waitTime;
-          _objectInspectorGB->setCheckTimer(waitTime);
-          _objectInspectorGB->setCheckUpdates(true);
-          _ui->actionConfigureREST->setEnabled(true);
+        const auto waitTime = m_loader->RESTLoader( )->getConfiguration( ).waitTime;
+        _objectInspectorGB->setCheckTimer( waitTime );
+        _objectInspectorGB->setCheckUpdates( true );
+        _ui->actionConfigureREST->setEnabled( true );
 #endif
-        }
+      }
         break;
       case simil::TDataType::TCONE:
       case simil::TDataType::TCSV:
@@ -2529,152 +2603,164 @@ void MainWindow::clearGroups( void )
         break;
     }
 
-    closeLoadingDialog();
+    closeLoadingDialog( );
 
-    if(!_lastOpenedSubsetsFileName.isEmpty())
+    if ( !_lastOpenedSubsetsFileName.isEmpty( ))
     {
-      openSubsetEventFile( _lastOpenedSubsetsFileName.toStdString() , false );
+      openSubsetEventFile( _lastOpenedSubsetsFileName.toStdString( ) , false );
     }
 
-    QApplication::restoreOverrideCursor();
+    QApplication::restoreOverrideCursor( );
   }
 
-  void MainWindow::onGroupNameClicked()
+  void MainWindow::onGroupNameClicked( )
   {
-    auto button = qobject_cast<QPushButton *>(sender());
-    if(button)
+    auto button = qobject_cast< QPushButton* >( sender( ));
+    if ( button )
     {
       bool ok = false;
-      size_t groupNum = button->property(GROUP_KEY).toUInt(&ok);
+      auto groupName = button->property( GROUP_NAME ).toString( );
 
-      if(!ok) return;
-      auto group = _domainManager->groups().at(groupNum);
+      if ( !ok ) return;
+      auto group = _domainManager->getGroup( groupName.toStdString( ));
 
-      auto groupName = QString::fromStdString(group->name());
-      groupName = QInputDialog::getText( this, tr( "Group Name" ),
-                                         tr( "Please, introduce group name: " ),
-                                         QLineEdit::Normal, groupName, &ok );
+      groupName = QInputDialog::getText( this , tr( "Group Name" ) ,
+                                         tr(
+                                           "Please, introduce group name: " ) ,
+                                         QLineEdit::Normal , groupName , &ok );
 
-      if (!ok) return;
-      group->name(groupName.toStdString());
-      button->setText(groupName);
+      if ( !ok ) return;
+      group->name( groupName.toStdString( ));
+      button->setText( groupName );
 
-      _stackViz->changeHistogramName( groupNum , groupName );
+      _stackViz->changeHistogramName( 0 , groupName );
     }
   }
 
-  void MainWindow::loadGroups()
+  void MainWindow::loadGroups( )
   {
-    const auto title = tr("Load Groups");
+    const auto title = tr( "Load Groups" );
 
-    if(!_domainManager->groups().empty())
+    if ( _domainManager->getGroupAmount( ) > 0 )
     {
-      const auto message = tr("Loading groups from disk will erase the "
-                              "current groups. Do you want to continue?");
+      const auto message = tr( "Loading groups from disk will erase the "
+                               "current groups. Do you want to continue?" );
 
-      QMessageBox msgbox(this);
-      msgbox.setWindowTitle(title);
-      msgbox.setText(message);
-      msgbox.setIcon(QMessageBox::Icon::Question);
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setStandardButtons(QMessageBox::Cancel|QMessageBox::Ok);
-      msgbox.setDefaultButton(QMessageBox::Button::Ok);
+      QMessageBox msgbox( this );
+      msgbox.setWindowTitle( title );
+      msgbox.setText( message );
+      msgbox.setIcon( QMessageBox::Icon::Question );
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setStandardButtons( QMessageBox::Cancel | QMessageBox::Ok );
+      msgbox.setDefaultButton( QMessageBox::Button::Ok );
 
-      if(QMessageBox::Ok != msgbox.exec())
+      if ( QMessageBox::Ok != msgbox.exec( ))
         return;
     }
 
-    QFileInfo lastFile{_lastOpenedNetworkFileName};
-    const auto fileName = QFileDialog::getOpenFileName(this, title, lastFile.path(),
-                                                       tr("Json files (*.json)"),
-                                                       nullptr, QFileDialog::ReadOnly|QFileDialog::DontUseNativeDialog);
-    if(fileName.isEmpty()) return;
-
-    QFile file{fileName};
-    if(!file.open(QIODevice::ReadOnly))
-    {
-      const auto message = tr("Couldn't open file %1").arg(fileName);
-
-      QMessageBox msgbox(this);
-      msgbox.setWindowTitle(title);
-      msgbox.setIcon(QMessageBox::Icon::Critical);
-      msgbox.setText(message);
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setStandardButtons(QMessageBox::Ok);
-      msgbox.exec();
+    QFileInfo lastFile{ _lastOpenedNetworkFileName };
+    const auto fileName = QFileDialog::getOpenFileName( this , title ,
+                                                        lastFile.path( ) ,
+                                                        tr(
+                                                          "Json files (*.json)" ) ,
+                                                        nullptr ,
+                                                        QFileDialog::ReadOnly |
+                                                        QFileDialog::DontUseNativeDialog );
+    if ( fileName.isEmpty( )) return;
+
+    QFile file{ fileName };
+    if ( !file.open( QIODevice::ReadOnly ))
+    {
+      const auto message = tr( "Couldn't open file %1" ).arg( fileName );
+
+      QMessageBox msgbox( this );
+      msgbox.setWindowTitle( title );
+      msgbox.setIcon( QMessageBox::Icon::Critical );
+      msgbox.setText( message );
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setStandardButtons( QMessageBox::Ok );
+      msgbox.exec( );
       return;
     }
 
-    const auto contents = file.readAll();
+    const auto contents = file.readAll( );
     QJsonParseError jsonError;
-    const auto  jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
-    if(jsonDoc.isNull() || !jsonDoc.isObject())
-    {
-      const auto message = tr("Couldn't read the contents of %1 or parsing error.").arg(fileName);
-
-      QMessageBox msgbox{this};
-      msgbox.setWindowTitle(title);
-      msgbox.setIcon(QMessageBox::Icon::Critical);
-      msgbox.setText(message);
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setStandardButtons(QMessageBox::Ok);
-      msgbox.setDetailedText(jsonError.errorString());
-      msgbox.exec();
+    const auto jsonDoc = QJsonDocument::fromJson( contents , &jsonError );
+    if ( jsonDoc.isNull( ) || !jsonDoc.isObject( ))
+    {
+      const auto message = tr(
+        "Couldn't read the contents of %1 or parsing error." ).arg( fileName );
+
+      QMessageBox msgbox{ this };
+      msgbox.setWindowTitle( title );
+      msgbox.setIcon( QMessageBox::Icon::Critical );
+      msgbox.setText( message );
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setStandardButtons( QMessageBox::Ok );
+      msgbox.setDetailedText( jsonError.errorString( ));
+      msgbox.exec( );
       return;
     }
 
-    const auto jsonObj = jsonDoc.object();
-    if(jsonObj.isEmpty())
+    const auto jsonObj = jsonDoc.object( );
+    if ( jsonObj.isEmpty( ))
     {
-      const auto message = tr("Error parsing the contents of %1.").arg(fileName);
+      const auto message = tr( "Error parsing the contents of %1." ).arg(
+        fileName );
 
-      QMessageBox msgbox{this};
-      msgbox.setWindowTitle(title);
-      msgbox.setIcon(QMessageBox::Icon::Critical);
-      msgbox.setText(message);
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setStandardButtons(QMessageBox::Ok);
-      msgbox.exec();
+      QMessageBox msgbox{ this };
+      msgbox.setWindowTitle( title );
+      msgbox.setIcon( QMessageBox::Icon::Critical );
+      msgbox.setText( message );
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setStandardButtons( QMessageBox::Ok );
+      msgbox.exec( );
       return;
     }
 
-    const QFileInfo currentFile{_lastOpenedNetworkFileName};
-    const QString jsonGroupsFile = jsonObj.value("filename").toString();
-    if(!jsonGroupsFile.isEmpty() && jsonGroupsFile.compare(currentFile.fileName(), Qt::CaseInsensitive) != 0)
+    const QFileInfo currentFile{ _lastOpenedNetworkFileName };
+    const QString jsonGroupsFile = jsonObj.value( "filename" ).toString( );
+    if ( !jsonGroupsFile.isEmpty( ) &&
+         jsonGroupsFile.compare( currentFile.fileName( ) ,
+                                 Qt::CaseInsensitive ) != 0 )
     {
-      const auto message = tr("This groups definitions are from file '%1'. Current file"
-                              " is '%2'. Do you want to continue?").arg(jsonGroupsFile).arg(currentFile.fileName());
+      const auto message = tr(
+        "This groups definitions are from file '%1'. Current file"
+        " is '%2'. Do you want to continue?" ).arg( jsonGroupsFile ).arg(
+        currentFile.fileName( ));
 
-      QMessageBox msgbox{this};
-      msgbox.setWindowTitle(title);
-      msgbox.setIcon(QMessageBox::Icon::Question);
-      msgbox.setText(message);
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setStandardButtons(QMessageBox::Cancel|QMessageBox::Ok);
-      msgbox.setDefaultButton(QMessageBox::Ok);
+      QMessageBox msgbox{ this };
+      msgbox.setWindowTitle( title );
+      msgbox.setIcon( QMessageBox::Icon::Question );
+      msgbox.setText( message );
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setStandardButtons( QMessageBox::Cancel | QMessageBox::Ok );
+      msgbox.setDefaultButton( QMessageBox::Ok );
 
-      if(QMessageBox::Ok != msgbox.exec())
+      if ( QMessageBox::Ok != msgbox.exec( ))
         return;
     }
 
-    QApplication::setOverrideCursor(Qt::WaitCursor);
+    QApplication::setOverrideCursor( Qt::WaitCursor );
+
+    _openGLWidget->makeCurrent( );
 
-    clearGroups();
-    const auto jsonGroups = jsonObj.value("groups").toArray();
+    clearGroups( );
+    const auto jsonGroups = jsonObj.value( "groups" ).toArray( );
 
-    std::vector<VisualGroup *> groupsList;
-    const auto createGroup = [&groupsList, this](const QJsonValue &v)
+    std::vector< VisualGroup* > groupsList;
+    const auto createGroup = [ this ]( const QJsonValue& v )
     {
-      const auto o = v.toObject();
+      const auto o = v.toObject( );
 
-      const auto name = o.value("name").toString();
-      const auto overrideGIDS = o.value("override").toBool(false);
-      const auto gidsStrings = o.value("gids").toString().split(",");
+      const auto name = o.value( "name" ).toString( );
+      //const auto overrideGIDS = o.value( "override" ).toBool( false );
+      const auto gidsStrings = o.value( "gids" ).toString( ).split( "," );
 
       GIDUSet gids;
-      auto addGids = [&gids](const QString s)
+      auto addGids = [ &gids ]( const QString s )
       {
-        if(s.contains(":"))
+        if ( s.contains( ":" ))
         {
           auto limits = s.split( ":" );
           for ( unsigned int id = limits.first( ).toUInt( );
@@ -2688,9 +2774,11 @@ void MainWindow::clearGroups( void )
       };
       std::for_each( gidsStrings.cbegin( ) , gidsStrings.cend( ) , addGids );
 
-      auto group = _domainManager->addVisualGroup( gids , name.toStdString( ) ,
-                                                   overrideGIDS );
-      auto idx = _domainManager->groups( ).size( ) - 1;
+      auto group = _domainManager->createGroup(
+        gids ,
+        _openGLWidget->getGidPositions( ) ,
+        name.toStdString( ));
+      auto idx = _domainManager->getGroupAmount( ) - 1;
       addGroupControls( group , idx , gids.size( ));
       const auto active = o.value( "active" ).toBool( true );
       auto checkbox = std::get< gr_checkbox >( _groupsVisButtons.at( idx ));
@@ -2702,7 +2790,7 @@ void MainWindow::clearGroups( void )
 
       _stackViz->addSelection( selection );
 
-      _domainManager->setVisualGroupState( idx , active );
+      group->active( active );
 
       const auto functionPairs = o.value( "function" ).toString( ).split( ";" );
       TTransferFunction function;
@@ -2714,638 +2802,684 @@ void MainWindow::clearGroups( void )
         const auto color = QColor( parts.last( ));
         function.emplace_back( value , color );
       };
-      std::for_each(functionPairs.cbegin(), functionPairs.cend(), addFunctionPair);
+      std::for_each( functionPairs.cbegin( ) , functionPairs.cend( ) ,
+                     addFunctionPair );
 
-      const auto sizePairs = o.value("sizes").toString().split(";");
+      const auto sizePairs = o.value( "sizes" ).toString( ).split( ";" );
       TSizeFunction sizes;
-      auto addSizes = [&sizes](const QString &s)
+      auto addSizes = [ &sizes ]( const QString& s )
       {
-        const auto parts = s.split(",");
-        Q_ASSERT(parts.size() == 2);
-        const auto a = parts.first().toFloat();
-        const auto b = parts.last().toFloat();
-        sizes.emplace_back(a, b);
+        const auto parts = s.split( "," );
+        Q_ASSERT( parts.size( ) == 2 );
+        const auto a = parts.first( ).toFloat( );
+        const auto b = parts.last( ).toFloat( );
+        sizes.emplace_back( a , b );
       };
-      std::for_each(sizePairs.cbegin(), sizePairs.cend(), addSizes);
+      std::for_each( sizePairs.cbegin( ) , sizePairs.cend( ) , addSizes );
 
-      updateGroupColors(idx, function, sizes);
-      auto container = std::get< gr_container >(_groupsVisButtons.at(idx));
-      auto tfw = qobject_cast<TransferFunctionWidget*>(container->layout()->itemAt(0)->widget());
-      if(tfw)
+      updateGroupColors( name.toStdString( ) , function , sizes );
+      auto container = std::get< gr_container >( _groupsVisButtons.at( idx ));
+      auto tfw = qobject_cast< TransferFunctionWidget* >(
+        container->layout( )->itemAt( 0 )->widget( ));
+      if ( tfw )
       {
-        tfw->setColorPoints(function, true);
-        tfw->setSizeFunction(sizes);
-        tfw->colorChanged();
-        tfw->sizeChanged();
+        tfw->setColorPoints( function , true );
+        tfw->setSizeFunction( sizes );
+        tfw->colorChanged( );
+        tfw->sizeChanged( );
       }
     };
-    std::for_each(jsonGroups.constBegin(), jsonGroups.constEnd(), createGroup);
+    std::for_each( jsonGroups.constBegin( ) , jsonGroups.constEnd( ) ,
+                   createGroup );
 
-    _groupLayout->update();
-    checkGroupsVisibility();
+    _groupLayout->update( );
+    checkGroupsVisibility( );
 
-    const auto groups = _domainManager->groups();
-    _buttonClearGroups->setEnabled( !groups.empty() );
-    _buttonSaveGroups->setEnabled( !groups.empty() );
+    bool notEmpty = _domainManager->getGroupAmount( ) > 0;
+    _buttonClearGroups->setEnabled( notEmpty );
+    _buttonSaveGroups->setEnabled( notEmpty );
+
+    _openGLWidget->update( );
 
-    QApplication::restoreOverrideCursor();
+    QApplication::restoreOverrideCursor( );
   }
 
-  void MainWindow::saveGroups()
+  void MainWindow::saveGroups( )
   {
-    const auto &groups = _domainManager->groups();
-    if(groups.empty()) return;
+    const auto& groups = _domainManager->getGroups( );
+    if ( groups.empty( )) return;
 
-    const auto dateTime = QDateTime::currentDateTime();
-    QFileInfo lastFile{_lastOpenedNetworkFileName};
-    QString filename = lastFile.dir().absoluteFilePath(lastFile.baseName() + "_groups_" + dateTime.toString("yyyy-MM-dd-hh-mm") + ".json");
-    filename = QFileDialog::getSaveFileName(this, tr("Save Groups"), filename, tr("Json files (*.json)"), nullptr, QFileDialog::DontUseNativeDialog);
+    const auto dateTime = QDateTime::currentDateTime( );
+    QFileInfo lastFile{ _lastOpenedNetworkFileName };
+    QString filename = lastFile.dir( ).absoluteFilePath(
+      lastFile.baseName( ) + "_groups_" +
+      dateTime.toString( "yyyy-MM-dd-hh-mm" ) + ".json" );
+    filename = QFileDialog::getSaveFileName( this , tr( "Save Groups" ) ,
+                                             filename ,
+                                             tr( "Json files (*.json)" ) ,
+                                             nullptr ,
+                                             QFileDialog::DontUseNativeDialog );
 
-    if(filename.isEmpty()) return;
+    if ( filename.isEmpty( )) return;
 
-    QFile wFile{filename};
-    if(!wFile.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate))
+    QFile wFile{ filename };
+    if ( !wFile.open(
+      QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ))
     {
-      const auto message = tr("Unable to open file %1 for writing.").arg(filename);
+      const auto message = tr( "Unable to open file %1 for writing." ).arg(
+        filename );
 
-      QMessageBox msgbox{this};
-      msgbox.setWindowTitle(tr("Save Groups"));
-      msgbox.setIcon(QMessageBox::Icon::Critical);
-      msgbox.setText(message);
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setDefaultButton(QMessageBox::Ok);
-      msgbox.exec();
+      QMessageBox msgbox{ this };
+      msgbox.setWindowTitle( tr( "Save Groups" ));
+      msgbox.setIcon( QMessageBox::Icon::Critical );
+      msgbox.setText( message );
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setDefaultButton( QMessageBox::Ok );
+      msgbox.exec( );
       return;
     }
 
-    QApplication::setOverrideCursor(Qt::WaitCursor);
+    QApplication::setOverrideCursor( Qt::WaitCursor );
 
     QJsonObject obj;
-    obj.insert("filename", QFileInfo{_lastOpenedNetworkFileName}.fileName());
-    obj.insert("date", dateTime.toString());
+    obj.insert( "filename" ,
+                QFileInfo{ _lastOpenedNetworkFileName }.fileName( ));
+    obj.insert( "date" , dateTime.toString( ));
 
     QJsonArray groupsObjs;
 
-    auto insertGroup = [&groupsObjs, this](const VisualGroup *g)
+    auto insertGroup = [ &groupsObjs ]( std::shared_ptr< VisualGroup > g )
     {
       QJsonObject groupObj;
-      groupObj.insert("name", QString::fromStdString(g->name()));
-      groupObj.insert("active", g->active());
+      groupObj.insert( "name" , QString::fromStdString( g->name( )));
+      groupObj.insert( "active" , g->active( ));
 
       QStringList tfList;
-      const auto tf = g->colorMapping();
-      auto addColors = [&tfList](const TTFColor &c)
+      const auto tf = g->colorMapping( );
+      auto addColors = [ &tfList ]( const TTFColor& c )
       {
-        tfList << QString("%1,%2").arg(c.first).arg(c.second.name(QColor::HexArgb));
+        tfList << QString( "%1,%2" ).arg( c.first ).arg(
+          c.second.name( QColor::HexArgb ));
       };
-      std::for_each(tf.cbegin(), tf.cend(), addColors);
-      groupObj.insert("function", tfList.join(";"));
+      std::for_each( tf.cbegin( ) , tf.cend( ) , addColors );
+      groupObj.insert( "function" , tfList.join( ";" ));
 
       QStringList sizesList;
-      const auto sizes = g->sizeFunction();
-      auto addSizes = [&sizesList](const TSize &s)
+      const auto sizes = g->sizeFunction( );
+      auto addSizes = [ &sizesList ]( const TSize& s )
       {
-        sizesList << QString("%1,%2").arg(s.first).arg(s.second);
+        sizesList << QString( "%1,%2" ).arg( s.first ).arg( s.second );
       };
-      std::for_each(sizes.cbegin(), sizes.cend(), addSizes);
-      groupObj.insert("sizes", sizesList.join(";"));
-
-      const auto &gids = g->gids();
-      std::vector<unsigned int> gidsVec;
-      std::for_each(gids.cbegin(), gids.cend(), [&gidsVec](unsigned int v){ gidsVec.push_back(v); });
-      std::sort(gidsVec.begin(), gidsVec.end());
+      std::for_each( sizes.cbegin( ) , sizes.cend( ) , addSizes );
+      groupObj.insert( "sizes" , sizesList.join( ";" ));
+
+      const auto& gids = g->getGids( );
+      std::vector< unsigned int > gidsVec;
+      std::for_each( gids.cbegin( ) , gids.cend( ) ,
+                     [ &gidsVec ]( unsigned int v )
+                     { gidsVec.push_back( v ); } );
+      std::sort( gidsVec.begin( ) , gidsVec.end( ));
       QStringList gidsStrings;
-      std::pair<unsigned int, unsigned int> range = std::make_pair(std::numeric_limits<unsigned int>::max() - 1,std::numeric_limits<unsigned int>::max() - 1);
-      auto enterNumber = [&range, &gidsStrings]()
+      std::pair< unsigned int , unsigned int > range = std::make_pair(
+        std::numeric_limits< unsigned int >::max( ) - 1 ,
+        std::numeric_limits< unsigned int >::max( ) - 1 );
+      auto enterNumber = [ &range , &gidsStrings ]( )
       {
-          if(range.first == range.second)
-            gidsStrings << QString::number(range.first);
-          else
-            gidsStrings << QString("%1:%2").arg(range.first).arg(range.second);
+        if ( range.first == range.second )
+          gidsStrings << QString::number( range.first );
+        else
+          gidsStrings
+            << QString( "%1:%2" ).arg( range.first ).arg( range.second );
       };
 
-      for(auto i = gidsVec.begin(); i != gidsVec.end(); ++i)
+      for ( auto i = gidsVec.begin( ); i != gidsVec.end( ); ++i )
       {
         auto num = *i;
-        if(num != range.second + 1)
+        if ( num != range.second + 1 )
         {
-          if(range.first != std::numeric_limits<unsigned int>::max() - 1)
+          if ( range.first != std::numeric_limits< unsigned int >::max( ) - 1 )
           {
-            enterNumber();
+            enterNumber( );
           }
           range.first = num;
         }
 
         range.second = num;
       }
-      enterNumber();
+      enterNumber( );
 
-      groupObj.insert("gids", gidsStrings.join(","));
+      groupObj.insert( "gids" , gidsStrings.join( "," ));
 
       groupsObjs << groupObj;
     };
-    std::for_each(groups.cbegin(), groups.cend(), insertGroup);
+    for ( const auto& item: groups )
+      insertGroup( item.second );
 
-    obj.insert("groups", groupsObjs);
+    obj.insert( "groups" , groupsObjs );
 
-    QJsonDocument doc{obj};
-    wFile.write(doc.toJson());
+    QJsonDocument doc{ obj };
+    wFile.write( doc.toJson( ));
 
-    QApplication::restoreOverrideCursor();
+    QApplication::restoreOverrideCursor( );
 
-    if(wFile.error() != QFile::NoError)
+    if ( wFile.error( ) != QFile::NoError )
     {
-      const auto message = tr("Error saving file %1.").arg(filename);
+      const auto message = tr( "Error saving file %1." ).arg( filename );
 
-      QMessageBox msgbox{this};
-      msgbox.setWindowTitle(tr("Save Groups"));
-      msgbox.setIcon(QMessageBox::Icon::Critical);
-      msgbox.setText(message);
-      msgbox.setDetailedText(wFile.errorString());
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setDefaultButton(QMessageBox::Ok);
-      msgbox.exec();
+      QMessageBox msgbox{ this };
+      msgbox.setWindowTitle( tr( "Save Groups" ));
+      msgbox.setIcon( QMessageBox::Icon::Critical );
+      msgbox.setText( message );
+      msgbox.setDetailedText( wFile.errorString( ));
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setDefaultButton( QMessageBox::Ok );
+      msgbox.exec( );
     }
 
-    wFile.flush();
-    wFile.close();
+    wFile.flush( );
+    wFile.close( );
   }
 
-  void MainWindow::onGroupDeleteClicked()
+  void MainWindow::onGroupDeleteClicked( )
   {
-    auto button = qobject_cast<QPushButton *>(sender());
-    if(button)
+    auto button = qobject_cast< QPushButton* >( sender( ));
+    if ( button )
     {
-      auto groupPtr = reinterpret_cast<VisualGroup *>(button->property(GROUP_POINTER_KEY).toULongLong());
-      auto groups = _domainManager->groups();
-      for(size_t i = 0; i < groups.size(); ++i)
-      {
-        if(groupPtr == groups.at(i))
-        {
-          removeVisualGroup(i);
-          return;
-        }
-      }
+      const auto groupName = button->property( GROUP_NAME ).toString( );
+      removeVisualGroup( groupName );
     }
   }
 
-  void MainWindow::removeVisualGroup(const unsigned int idx)
+  void MainWindow::removeVisualGroup( const QString& name )
   {
-    auto row = _groupsVisButtons.at(idx);
-    auto container = std::get< gr_container >( row );
+    auto findGroup = [ this , name ]( tGroupRow& r )
+    {
+      QWidget* container = std::get< gr_container >( r );
+      auto groupName = container->property( GROUP_NAME ).toString( );
+      return groupName.compare( name , Qt::CaseInsensitive ) == 0;
+    };
+    auto it = std::find_if( _groupsVisButtons.begin( ) ,
+                            _groupsVisButtons.end( ) , findGroup );
+    if ( it == _groupsVisButtons.end( )) return;
 
+    auto container = std::get< gr_container >( *it );
     _groupLayout->removeWidget( container );
-
     delete container;
+    const auto idx = std::distance( _groupsVisButtons.begin( ) , it );
 
-    _domainManager->removeVisualGroup( idx );
+    _domainManager->removeGroup( name.toStdString( ));
 
     _stackViz->removeSubset( idx );
 
-    _groupsVisButtons.erase(_groupsVisButtons.begin() + idx);
+    _groupsVisButtons.erase( _groupsVisButtons.begin( ) + idx );
 
-    const bool enabled = !_groupsVisButtons.empty();
+    const bool enabled = !_groupsVisButtons.empty( );
     _buttonClearGroups->setEnabled( enabled );
-    _buttonSaveGroups->setEnabled( enabled);
-
-    _openGLWidget->setUpdateGroups( );
+    _buttonSaveGroups->setEnabled( enabled );
   }
 
-  void MainWindow::changeStackVizToolbarStatus(bool status)
+  void MainWindow::changeStackVizToolbarStatus( bool status )
   {
-    _ui->actionStackVizAutoNamingSelections->setEnabled(status);
-    _ui->actionStackVizFillPlots->setEnabled(status);
-    _ui->actionStackVizFocusOnPlayhead->setEnabled(status);
-    _ui->actionStackVizFollowPlayHead->setEnabled(status);
-    _ui->actionStackVizShowDataManager->setEnabled(status);
-    _ui->actionStackVizShowPanels->setEnabled(status);
+    _ui->actionStackVizAutoNamingSelections->setEnabled( status );
+    _ui->actionStackVizFillPlots->setEnabled( status );
+    _ui->actionStackVizFocusOnPlayhead->setEnabled( status );
+    _ui->actionStackVizFollowPlayHead->setEnabled( status );
+    _ui->actionStackVizShowDataManager->setEnabled( status );
+    _ui->actionStackVizShowPanels->setEnabled( status );
   }
 
   void MainWindow::finishRecording( )
   {
-    auto recorderAction = _ui->menuTools->actions().first();
+    auto recorderAction = _ui->menuTools->actions( ).first( );
     recorderAction->setEnabled( true );
     recorderAction->setChecked( false );
   }
 
-  void MainWindow::closeEvent(QCloseEvent *e)
+  void MainWindow::closeEvent( QCloseEvent* e )
   {
-    if(_recorder)
+    if ( _recorder )
     {
-      QMessageBox msgBox(this);
-      msgBox.setWindowTitle(tr("Exit SimPart"));
+      QMessageBox msgBox( this );
+      msgBox.setWindowTitle( tr( "Exit SimPart" ));
       msgBox.setWindowIcon( QIcon( ":/visimpl.png" ));
-      msgBox.setText(tr("A recording is being made. Do you really want to exit SimPart?"));
-      msgBox.setStandardButtons(QMessageBox::Cancel|QMessageBox::Yes);
+      msgBox.setText(
+        tr( "A recording is being made. Do you really want to exit SimPart?" ));
+      msgBox.setStandardButtons( QMessageBox::Cancel | QMessageBox::Yes );
 
-      if(msgBox.exec() != QMessageBox::Yes)
+      if ( msgBox.exec( ) != QMessageBox::Yes )
       {
-        e->ignore();
+        e->ignore( );
         return;
       }
 
-      RecorderUtils::stopAndWait(_recorder, this);
+      RecorderUtils::stopAndWait( _recorder , this );
       _recorder = nullptr;
     }
 
-    QMainWindow::closeEvent(e);
+    QMainWindow::closeEvent( e );
   }
 
-  void MainWindow::loadCameraPositions()
+  void MainWindow::loadCameraPositions( )
   {
     const QString title = "Load camera positions";
 
-    auto actions = _ui->actionCamera_Positions->menu()->actions();
-    const auto numActions = actions.size();
-    if(numActions > 0)
+    auto actions = _ui->actionCamera_Positions->menu( )->actions( );
+    const auto numActions = actions.size( );
+    if ( numActions > 0 )
     {
-      const auto warnText = tr("Loading new camera positions will remove"
-                               " %1 existing position%2. Are you sure?").arg(numActions).arg(numActions > 1 ? "s":"");
-      if(QMessageBox::Ok != QMessageBox::warning(this, title, warnText, QMessageBox::Cancel|QMessageBox::Ok))
+      const auto warnText = tr( "Loading new camera positions will remove"
+                                " %1 existing position%2. Are you sure?" ).arg(
+        numActions ).arg( numActions > 1 ? "s" : "" );
+      if ( QMessageBox::Ok != QMessageBox::warning( this , title , warnText ,
+                                                    QMessageBox::Cancel |
+                                                    QMessageBox::Ok ))
         return;
     }
 
     const QString nameFilter = "Camera positions (*.json)";
     QDir directory;
 
-    if(_lastOpenedNetworkFileName.isEmpty())
-      directory = QDir::home();
+    if ( _lastOpenedNetworkFileName.isEmpty( ))
+      directory = QDir::home( );
     else
-      directory = QFileInfo(_lastOpenedNetworkFileName).dir();
-
-    QFileDialog fDialog(this);
-    fDialog.setWindowIcon(QIcon(":/visimpl.png"));
-    fDialog.setWindowTitle(title);
-    fDialog.setAcceptMode(QFileDialog::AcceptMode::AcceptOpen);
-    fDialog.setDefaultSuffix("json");
-    fDialog.setDirectory(directory);
-    fDialog.setOption(QFileDialog::Option::DontUseNativeDialog, true);
-    fDialog.setFileMode(QFileDialog::FileMode::ExistingFile);
-    fDialog.setNameFilters(QStringList{nameFilter});
-    fDialog.setNameFilter(nameFilter);
-
-    if(fDialog.exec() != QFileDialog::Accepted)
+      directory = QFileInfo( _lastOpenedNetworkFileName ).dir( );
+
+    QFileDialog fDialog( this );
+    fDialog.setWindowIcon( QIcon( ":/visimpl.png" ));
+    fDialog.setWindowTitle( title );
+    fDialog.setAcceptMode( QFileDialog::AcceptMode::AcceptOpen );
+    fDialog.setDefaultSuffix( "json" );
+    fDialog.setDirectory( directory );
+    fDialog.setOption( QFileDialog::Option::DontUseNativeDialog , true );
+    fDialog.setFileMode( QFileDialog::FileMode::ExistingFile );
+    fDialog.setNameFilters( QStringList{ nameFilter } );
+    fDialog.setNameFilter( nameFilter );
+
+    if ( fDialog.exec( ) != QFileDialog::Accepted )
       return;
 
-    if(fDialog.selectedFiles().empty()) return;
+    if ( fDialog.selectedFiles( ).empty( )) return;
 
-    auto file = fDialog.selectedFiles().first();
+    auto file = fDialog.selectedFiles( ).first( );
 
-    QFile posFile{file};
-    if(!posFile.open(QIODevice::ReadOnly|QIODevice::Text))
+    QFile posFile{ file };
+    if ( !posFile.open( QIODevice::ReadOnly | QIODevice::Text ))
     {
-      const QString errorText = tr("Unable to open: %1").arg(file);
-      QMessageBox::critical(this, title, errorText);
+      const QString errorText = tr( "Unable to open: %1" ).arg( file );
+      QMessageBox::critical( this , title , errorText );
       return;
     }
 
-    const auto contents = posFile.readAll();
+    const auto contents = posFile.readAll( );
     QJsonParseError parserError;
 
-    const auto  jsonDoc = QJsonDocument::fromJson(contents, &parserError);
-    if(jsonDoc.isNull() || !jsonDoc.isObject())
+    const auto jsonDoc = QJsonDocument::fromJson( contents , &parserError );
+    if ( jsonDoc.isNull( ) || !jsonDoc.isObject( ))
     {
-      const auto message = tr("Couldn't read the contents of %1 or parsing error.").arg(file);
+      const auto message = tr(
+        "Couldn't read the contents of %1 or parsing error." ).arg( file );
 
-      QMessageBox msgbox{this};
-      msgbox.setWindowTitle(title);
-      msgbox.setIcon(QMessageBox::Icon::Critical);
-      msgbox.setText(message);
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setStandardButtons(QMessageBox::Ok);
-      msgbox.setDetailedText(parserError.errorString());
-      msgbox.exec();
+      QMessageBox msgbox{ this };
+      msgbox.setWindowTitle( title );
+      msgbox.setIcon( QMessageBox::Icon::Critical );
+      msgbox.setText( message );
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setStandardButtons( QMessageBox::Ok );
+      msgbox.setDetailedText( parserError.errorString( ));
+      msgbox.exec( );
       return;
     }
 
-    const auto jsonObj = jsonDoc.object();
-    if(jsonObj.isEmpty())
+    const auto jsonObj = jsonDoc.object( );
+    if ( jsonObj.isEmpty( ))
     {
-      const auto message = tr("Error parsing the contents of %1.").arg(file);
+      const auto message = tr( "Error parsing the contents of %1." ).arg(
+        file );
 
-      QMessageBox msgbox{this};
-      msgbox.setWindowTitle(title);
-      msgbox.setIcon(QMessageBox::Icon::Critical);
-      msgbox.setText(message);
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setStandardButtons(QMessageBox::Ok);
-      msgbox.exec();
+      QMessageBox msgbox{ this };
+      msgbox.setWindowTitle( title );
+      msgbox.setIcon( QMessageBox::Icon::Critical );
+      msgbox.setText( message );
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setStandardButtons( QMessageBox::Ok );
+      msgbox.exec( );
       return;
     }
 
-    const QFileInfo currentFile{_lastOpenedNetworkFileName};
-    const QString jsonPositionsFile = jsonObj.value("filename").toString();
-    if(!jsonPositionsFile.isEmpty() && jsonPositionsFile.compare(currentFile.fileName(), Qt::CaseInsensitive) != 0)
+    const QFileInfo currentFile{ _lastOpenedNetworkFileName };
+    const QString jsonPositionsFile = jsonObj.value( "filename" ).toString( );
+    if ( !jsonPositionsFile.isEmpty( ) &&
+         jsonPositionsFile.compare( currentFile.fileName( ) ,
+                                    Qt::CaseInsensitive ) != 0 )
     {
-      const auto message = tr("This positions are from file '%1'. Current file"
-                              " is '%2'. Do you want to continue?").arg(jsonPositionsFile).arg(currentFile.fileName());
+      const auto message = tr( "This positions are from file '%1'. Current file"
+                               " is '%2'. Do you want to continue?" ).arg(
+        jsonPositionsFile ).arg( currentFile.fileName( ));
 
-      QMessageBox msgbox{this};
-      msgbox.setWindowTitle(title);
-      msgbox.setIcon(QMessageBox::Icon::Question);
-      msgbox.setText(message);
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setStandardButtons(QMessageBox::Cancel|QMessageBox::Ok);
-      msgbox.setDefaultButton(QMessageBox::Ok);
+      QMessageBox msgbox{ this };
+      msgbox.setWindowTitle( title );
+      msgbox.setIcon( QMessageBox::Icon::Question );
+      msgbox.setText( message );
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setStandardButtons( QMessageBox::Cancel | QMessageBox::Ok );
+      msgbox.setDefaultButton( QMessageBox::Ok );
 
-      if(QMessageBox::Ok != msgbox.exec())
+      if ( QMessageBox::Ok != msgbox.exec( ))
         return;
     }
 
     // Clear existing actions before entering new ones.
-    for(auto action: actions)
+    for ( auto action: actions )
     {
-      _ui->actionCamera_Positions->menu()->removeAction(action);
+      _ui->actionCamera_Positions->menu( )->removeAction( action );
       delete action;
     }
 
-    const auto jsonPositions = jsonObj.value("positions").toArray();
+    const auto jsonPositions = jsonObj.value( "positions" ).toArray( );
 
-    auto createPosition = [this](const QJsonValue &v)
+    auto createPosition = [ this ]( const QJsonValue& v )
     {
-      const auto o = v.toObject();
+      const auto o = v.toObject( );
 
-      const auto name = o.value("name").toString();
-      const auto position = o.value("position").toString();
-      const auto radius = o.value("radius").toString();
-      const auto rotation = o.value("rotation").toString();
+      const auto name = o.value( "name" ).toString( );
+      const auto position = o.value( "position" ).toString( );
+      const auto radius = o.value( "radius" ).toString( );
+      const auto rotation = o.value( "rotation" ).toString( );
 
-      auto action = new QAction(name);
-      action->setProperty(POSITION_KEY, position + ";" + radius + ";" + rotation);
+      auto action = new QAction( name );
+      action->setProperty( POSITION_KEY ,
+                           position + ";" + radius + ";" + rotation );
 
-      connect(action, SIGNAL(triggered(bool)), this, SLOT(applyCameraPosition()));
+      connect( action , SIGNAL( triggered( bool )) , this ,
+               SLOT( applyCameraPosition( )) );
 
-      _ui->actionCamera_Positions->menu()->addAction(action);
+      _ui->actionCamera_Positions->menu( )->addAction( action );
     };
-    std::for_each(jsonPositions.constBegin(), jsonPositions.constEnd(), createPosition);
+    std::for_each( jsonPositions.constBegin( ) , jsonPositions.constEnd( ) ,
+                   createPosition );
 
-    const bool positionsExist = !_ui->actionCamera_Positions->menu()->actions().isEmpty();
-    _ui->actionSave_camera_positions->setEnabled(positionsExist);
-    _ui->actionRemove_camera_position->setEnabled(positionsExist);
-    _ui->actionCamera_Positions->setEnabled(positionsExist);
+    const bool positionsExist = !_ui->actionCamera_Positions->menu( )->actions( ).isEmpty( );
+    _ui->actionSave_camera_positions->setEnabled( positionsExist );
+    _ui->actionRemove_camera_position->setEnabled( positionsExist );
+    _ui->actionCamera_Positions->setEnabled( positionsExist );
   }
 
-  void MainWindow::saveCameraPositions()
+  void MainWindow::saveCameraPositions( )
   {
     const QString nameFilter = "Camera positions (*.json)";
     QDir directory;
     QString filename;
 
-    if(_lastOpenedNetworkFileName.isEmpty())
+    if ( _lastOpenedNetworkFileName.isEmpty( ))
     {
-      directory = QDir::home();
+      directory = QDir::home( );
       filename = "positions.json";
     }
     else
     {
-      QFileInfo fi(_lastOpenedNetworkFileName);
-      directory = fi.dir();
-      filename = QString("%1_positions.json").arg(fi.baseName());
-    }
-
-    QFileDialog fDialog(this);
-    fDialog.setWindowIcon(QIcon(":/visimpl.png"));
-    fDialog.setWindowTitle("Save camera positions");
-    fDialog.setAcceptMode(QFileDialog::AcceptMode::AcceptSave);
-    fDialog.setDefaultSuffix("json");
-    fDialog.selectFile(filename);
-    fDialog.setDirectory(directory);
-    fDialog.setOption(QFileDialog::Option::DontUseNativeDialog, true);
-    fDialog.setOption(QFileDialog::Option::DontConfirmOverwrite, false);
-    fDialog.setFileMode(QFileDialog::FileMode::AnyFile);
-    fDialog.setNameFilters(QStringList{nameFilter});
-    fDialog.setNameFilter(nameFilter);
-
-    if(fDialog.exec() != QFileDialog::Accepted)
+      QFileInfo fi( _lastOpenedNetworkFileName );
+      directory = fi.dir( );
+      filename = QString( "%1_positions.json" ).arg( fi.baseName( ));
+    }
+
+    QFileDialog fDialog( this );
+    fDialog.setWindowIcon( QIcon( ":/visimpl.png" ));
+    fDialog.setWindowTitle( "Save camera positions" );
+    fDialog.setAcceptMode( QFileDialog::AcceptMode::AcceptSave );
+    fDialog.setDefaultSuffix( "json" );
+    fDialog.selectFile( filename );
+    fDialog.setDirectory( directory );
+    fDialog.setOption( QFileDialog::Option::DontUseNativeDialog , true );
+    fDialog.setOption( QFileDialog::Option::DontConfirmOverwrite , false );
+    fDialog.setFileMode( QFileDialog::FileMode::AnyFile );
+    fDialog.setNameFilters( QStringList{ nameFilter } );
+    fDialog.setNameFilter( nameFilter );
+
+    if ( fDialog.exec( ) != QFileDialog::Accepted )
       return;
 
-    if(fDialog.selectedFiles().empty()) return;
+    if ( fDialog.selectedFiles( ).empty( )) return;
 
-    filename = fDialog.selectedFiles().first();
+    filename = fDialog.selectedFiles( ).first( );
 
-    QFile wFile{filename};
-    if(!wFile.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate))
+    QFile wFile{ filename };
+    if ( !wFile.open(
+      QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ))
     {
-      const auto message = tr("Unable to open file %1 for writing.").arg(filename);
+      const auto message = tr( "Unable to open file %1 for writing." ).arg(
+        filename );
 
-      QMessageBox msgbox{this};
-      msgbox.setWindowTitle(tr("Save camera positions"));
-      msgbox.setIcon(QMessageBox::Icon::Critical);
-      msgbox.setText(message);
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setDefaultButton(QMessageBox::Ok);
-      msgbox.exec();
+      QMessageBox msgbox{ this };
+      msgbox.setWindowTitle( tr( "Save camera positions" ));
+      msgbox.setIcon( QMessageBox::Icon::Critical );
+      msgbox.setText( message );
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setDefaultButton( QMessageBox::Ok );
+      msgbox.exec( );
       return;
     }
 
-    QApplication::setOverrideCursor(Qt::WaitCursor);
+    QApplication::setOverrideCursor( Qt::WaitCursor );
 
-    const auto actions = _ui->actionCamera_Positions->menu()->actions();
+    const auto actions = _ui->actionCamera_Positions->menu( )->actions( );
 
     QJsonArray positionsObjs;
 
-    auto insertPosition = [&positionsObjs, this](const QAction *a)
+    auto insertPosition = [ &positionsObjs ]( const QAction* a )
     {
-      if(!a) return;
-      const auto posData = a->property(POSITION_KEY).toString();
-      const auto parts = posData.split(";");
-      Q_ASSERT(parts.size() == 3);
-      const auto position = parts.first();
-      const auto radius = parts.at(1);
-      const auto rotation = parts.last();
+      if ( !a ) return;
+      const auto posData = a->property( POSITION_KEY ).toString( );
+      const auto parts = posData.split( ";" );
+      Q_ASSERT( parts.size( ) == 3 );
+      const auto position = parts.first( );
+      const auto radius = parts.at( 1 );
+      const auto rotation = parts.last( );
 
       QJsonObject positionObj;
-      positionObj.insert("name", a->text());
-      positionObj.insert("position", position);
-      positionObj.insert("radius", radius);
-      positionObj.insert("rotation", rotation);
+      positionObj.insert( "name" , a->text( ));
+      positionObj.insert( "position" , position );
+      positionObj.insert( "radius" , radius );
+      positionObj.insert( "rotation" , rotation );
 
       positionsObjs << positionObj;
     };
-    std::for_each(actions.cbegin(), actions.cend(), insertPosition);
+    std::for_each( actions.cbegin( ) , actions.cend( ) , insertPosition );
 
     QJsonObject obj;
-    obj.insert("filename", QFileInfo{_lastOpenedNetworkFileName}.fileName());
-    obj.insert("positions", positionsObjs);
+    obj.insert( "filename" ,
+                QFileInfo{ _lastOpenedNetworkFileName }.fileName( ));
+    obj.insert( "positions" , positionsObjs );
 
-    QJsonDocument doc{obj};
-    wFile.write(doc.toJson());
+    QJsonDocument doc{ obj };
+    wFile.write( doc.toJson( ));
 
-    QApplication::restoreOverrideCursor();
+    QApplication::restoreOverrideCursor( );
 
-    if(wFile.error() != QFile::NoError)
+    if ( wFile.error( ) != QFile::NoError )
     {
-      const auto message = tr("Error saving file %1.").arg(filename);
+      const auto message = tr( "Error saving file %1." ).arg( filename );
 
-      QMessageBox msgbox{this};
-      msgbox.setWindowTitle(tr("Save camera positions"));
-      msgbox.setIcon(QMessageBox::Icon::Critical);
-      msgbox.setText(message);
-      msgbox.setDetailedText(wFile.errorString());
-      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
-      msgbox.setDefaultButton(QMessageBox::Ok);
-      msgbox.exec();
+      QMessageBox msgbox{ this };
+      msgbox.setWindowTitle( tr( "Save camera positions" ));
+      msgbox.setIcon( QMessageBox::Icon::Critical );
+      msgbox.setText( message );
+      msgbox.setDetailedText( wFile.errorString( ));
+      msgbox.setWindowIcon( QIcon( ":/visimpl.png" ));
+      msgbox.setDefaultButton( QMessageBox::Ok );
+      msgbox.exec( );
     }
 
-    wFile.flush();
-    wFile.close();
+    wFile.flush( );
+    wFile.close( );
   }
 
-  void MainWindow::addCameraPosition()
+  void MainWindow::addCameraPosition( )
   {
     QStringList items;
 
-    auto actions = _ui->actionCamera_Positions->menu()->actions();
-    auto insertItemName = [&items](const QAction *a){ items << a->text(); };
-    std::for_each(actions.cbegin(), actions.cend(), insertItemName);
+    auto actions = _ui->actionCamera_Positions->menu( )->actions( );
+    auto insertItemName = [ &items ]( const QAction* a )
+    { items << a->text( ); };
+    std::for_each( actions.cbegin( ) , actions.cend( ) , insertItemName );
 
-    const QString title = tr("Add camera position");
+    const QString title = tr( "Add camera position" );
 
     bool ok = false;
     QString name;
-    while(!ok || name.isEmpty())
+    while ( !ok || name.isEmpty( ))
     {
-      name = QInputDialog::getText(this, title, tr("Position name:"), QLineEdit::Normal, tr("New position"), &ok);
+      name = QInputDialog::getText( this , title , tr( "Position name:" ) ,
+                                    QLineEdit::Normal , tr( "New position" ) ,
+                                    &ok );
 
-      if(ok && !name.isEmpty())
+      if ( ok && !name.isEmpty( ))
       {
-        QString tempName(name);
+        QString tempName( name );
         int collision = 0;
-        while(items.contains(tempName, Qt::CaseInsensitive))
+        while ( items.contains( tempName , Qt::CaseInsensitive ))
         {
           ++collision;
-          tempName = tr("%1 (%2)").arg(name).arg(collision);
+          tempName = tr( "%1 (%2)" ).arg( name ).arg( collision );
         }
 
         name = tempName;
       }
     }
 
-    auto action = new QAction(name);
+    auto action = new QAction( name );
 
-    const auto position = _openGLWidget->cameraPosition();
-    action->setProperty(POSITION_KEY, position.toString());
+    const auto position = _openGLWidget->cameraPosition( );
+    action->setProperty( POSITION_KEY , position.toString( ));
 
-    connect(action, SIGNAL(triggered(bool)), this, SLOT(applyCameraPosition()));
-    _ui->actionCamera_Positions->menu()->addAction(action);
-    _ui->actionCamera_Positions->setEnabled(true);
-    _ui->actionSave_camera_positions->setEnabled(true);
-    _ui->actionRemove_camera_position->setEnabled(true);
+    connect( action , SIGNAL( triggered( bool )) , this ,
+             SLOT( applyCameraPosition( )) );
+    _ui->actionCamera_Positions->menu( )->addAction( action );
+    _ui->actionCamera_Positions->setEnabled( true );
+    _ui->actionSave_camera_positions->setEnabled( true );
+    _ui->actionRemove_camera_position->setEnabled( true );
   }
 
-  void MainWindow::removeCameraPosition()
+  void MainWindow::removeCameraPosition( )
   {
     bool ok = false;
     QStringList items;
 
-    auto actions = _ui->actionCamera_Positions->menu()->actions();
-    auto insertItemName = [&items](const QAction *a){ items << a->text(); };
-    std::for_each(actions.cbegin(), actions.cend(), insertItemName);
-
-    auto item = QInputDialog::getItem(this, tr("Remove camera position"), tr("Position name:"), items, 0, false, &ok);
-    if (ok && !item.isEmpty())
-    {
-      auto actionOfName = [&item](const QAction *a){ return a->text() == item; };
-      const auto it = std::find_if(actions.cbegin(), actions.cend(), actionOfName);
-      auto distance = std::distance(actions.cbegin(), it);
-      auto action = actions.at(distance);
-      _ui->actionCamera_Positions->menu()->removeAction(action);
+    auto actions = _ui->actionCamera_Positions->menu( )->actions( );
+    auto insertItemName = [ &items ]( const QAction* a )
+    { items << a->text( ); };
+    std::for_each( actions.cbegin( ) , actions.cend( ) , insertItemName );
+
+    auto item = QInputDialog::getItem( this , tr( "Remove camera position" ) ,
+                                       tr( "Position name:" ) , items , 0 ,
+                                       false , &ok );
+    if ( ok && !item.isEmpty( ))
+    {
+      auto actionOfName = [ &item ]( const QAction* a )
+      { return a->text( ) == item; };
+      const auto it = std::find_if( actions.cbegin( ) , actions.cend( ) ,
+                                    actionOfName );
+      auto distance = std::distance( actions.cbegin( ) , it );
+      auto action = actions.at( distance );
+      _ui->actionCamera_Positions->menu( )->removeAction( action );
       delete action;
 
-      const auto enabled = actions.size() > 1;
-      _ui->actionRemove_camera_position->setEnabled(enabled);
-      _ui->actionSave_camera_positions->setEnabled(enabled);
-      _ui->actionCamera_Positions->setEnabled(enabled);
+      const auto enabled = actions.size( ) > 1;
+      _ui->actionRemove_camera_position->setEnabled( enabled );
+      _ui->actionSave_camera_positions->setEnabled( enabled );
+      _ui->actionCamera_Positions->setEnabled( enabled );
     }
   }
 
-  void MainWindow::applyCameraPosition()
+  void MainWindow::applyCameraPosition( )
   {
-    auto action = qobject_cast<QAction *>(sender());
-    if(action)
+    auto action = qobject_cast< QAction* >( sender( ));
+    if ( action )
     {
-      auto positionString = action->property(POSITION_KEY).toString();
-      CameraPosition position(positionString);
-      _openGLWidget->setCameraPosition(position);
+      auto positionString = action->property( POSITION_KEY ).toString( );
+      CameraPosition position( positionString );
+      _openGLWidget->setCameraPosition( position );
     }
   }
 
-  void MainWindow::openRESTThroughDialog()
+  void MainWindow::openRESTThroughDialog( )
   {
 #ifdef SIMIL_WITH_REST_API
-    ConnectRESTDialog dialog(this);
+    ConnectRESTDialog dialog( this );
     ConnectRESTDialog::Connection connection;
-    dialog.setRESTConnection(connection);
+    dialog.setRESTConnection( connection );
 
-    if(QDialog::Accepted == dialog.exec())
+    if ( QDialog::Accepted == dialog.exec( ))
     {
-      connection = dialog.getRESTConnection();
-      const auto restOpt = dialog.getRESTOptions();
+      connection = dialog.getRESTConnection( );
+      const auto restOpt = dialog.getRESTOptions( );
 
       simil::LoaderRestData::Configuration config;
-      config.api = connection.protocol.compare("NEST", Qt::CaseInsensitive) == 0 ?
-                                        simil::LoaderRestData::Rest_API::NEST :
-                                        simil::LoaderRestData::Rest_API::ARBOR;
+      config.api =
+        connection.protocol.compare( "NEST" , Qt::CaseInsensitive ) == 0 ?
+        simil::LoaderRestData::Rest_API::NEST :
+        simil::LoaderRestData::Rest_API::ARBOR;
       config.port = connection.port;
-      config.url = connection.url.toStdString();
+      config.url = connection.url.toStdString( );
       config.waitTime = restOpt.waitTime;
       config.failTime = restOpt.failTime;
       config.spikesSize = restOpt.spikesSize;
 
-      loadRESTData(config);
+      loadRESTData( config );
     }
 #else
-    const auto title = tr("Connect REST API");
-    const auto message = tr("REST data loading is unsupported.");
-    QMessageBox::critical(this, title, message, QMessageBox::Ok);
+    const auto title = tr( "Connect REST API" );
+    const auto message = tr( "REST data loading is unsupported." );
+    QMessageBox::critical( this , title , message , QMessageBox::Ok );
 #endif
   }
 
-  void MainWindow::configureREST()
+  void MainWindow::configureREST( )
   {
 #ifdef SIMIL_WITH_REST_API
-    if(!m_loader)
+    if ( !m_loader )
     {
-      const QString message = tr("There is no REST connection!");
-      QMessageBox::warning(this, tr("REST API Options"), message, QMessageBox::Ok);
+      const QString message = tr( "There is no REST connection!" );
+      QMessageBox::warning( this , tr( "REST API Options" ) , message ,
+                            QMessageBox::Ok );
       return;
     }
 
-    auto loader = m_loader->RESTLoader();
-    auto options = loader->getConfiguration();
+    auto loader = m_loader->RESTLoader( );
+    auto options = loader->getConfiguration( );
 
     RESTConfigurationWidget::Options dialogOptions;
     dialogOptions.waitTime = options.waitTime;
     dialogOptions.failTime = options.failTime;
     dialogOptions.spikesSize = options.spikesSize;
 
-    ConfigureRESTDialog dialog(this, Qt::WindowFlags(), dialogOptions);
-    if(QDialog::Accepted == dialog.exec())
+    ConfigureRESTDialog dialog( this , Qt::WindowFlags( ) , dialogOptions );
+    if ( QDialog::Accepted == dialog.exec( ))
     {
-      dialogOptions = dialog.getRESTOptions();
+      dialogOptions = dialog.getRESTOptions( );
 
       simil::LoaderRestData::Configuration config;
       config.waitTime = dialogOptions.waitTime;
       config.failTime = dialogOptions.failTime;
       config.spikesSize = dialogOptions.spikesSize;
 
-      loader->setConfiguration(config);
+      loader->setConfiguration( config );
     }
 #else
-    const auto title = tr("Configure REST API");
-    const auto message = tr("REST data loading is unsupported.");
-    QMessageBox::critical(this, title, message, QMessageBox::Ok);
+    const auto title = tr( "Configure REST API" );
+    const auto message = tr( "REST data loading is unsupported." );
+    QMessageBox::critical( this , title , message , QMessageBox::Ok );
 #endif
   }
 
 #ifdef SIMIL_WITH_REST_API
-  void MainWindow::loadRESTData(const simil::LoaderRestData::Configuration &o)
+
+  void MainWindow::loadRESTData( const simil::LoaderRestData::Configuration& o )
   {
-    closeLoadingDialog();
+    closeLoadingDialog( );
 
-    QApplication::setOverrideCursor(Qt::WaitCursor);
+    QApplication::setOverrideCursor( Qt::WaitCursor );
 
-    _objectInspectorGB->setCheckUpdates(false);
+    _objectInspectorGB->setCheckUpdates( false );
 
     m_loaderDialog = new LoadingDialog( this );
     m_loaderDialog->show( );
@@ -3353,48 +3487,53 @@ void MainWindow::clearGroups( void )
     QApplication::processEvents( );
 
     m_loader = std::make_shared< LoaderThread >( );
-    m_loader->setRESTConfiguration(o);
+    m_loader->setRESTConfiguration( o );
 
-    connect( m_loader.get( ) , SIGNAL( finished( )),
-             this, SLOT( onDataLoaded( )) );
-    connect( m_loader.get( ) , SIGNAL( progress( int )),
-             m_loaderDialog , SLOT( setProgress( int )) );
+    connect( m_loader.get( ) , SIGNAL( finished( )) ,
+             this , SLOT( onDataLoaded( )));
+    connect( m_loader.get( ) , SIGNAL( progress( int )) ,
+             m_loaderDialog , SLOT( setProgress( int )));
     connect( m_loader.get( ) , SIGNAL( network( unsigned int )) ,
-             m_loaderDialog , SLOT( setNetwork( unsigned int )) );
+             m_loaderDialog , SLOT( setNetwork( unsigned int )));
     connect( m_loader.get( ) , SIGNAL( spikes( unsigned int )) ,
-             m_loaderDialog , SLOT( setSpikesValue( unsigned int )) );
+             m_loaderDialog , SLOT( setSpikesValue( unsigned int )));
 
     m_loader->start( );
   }
+
 #endif
 
-  void MainWindow::changePlanesColor(const QColor &color_)
+  void MainWindow::changePlanesColor( const QColor& color_ )
   {
-    const auto currentColor = QColor( _frameClippingColor->property(PLANES_COLOR_KEY).toString());
-    if(currentColor == color_) return;
+    const auto currentColor = QColor(
+      _frameClippingColor->property( PLANES_COLOR_KEY ).toString( ));
+    if ( currentColor == color_ ) return;
 
-    _frameClippingColor->setStyleSheet( "background-color: " + color_.name( ) );
-    _frameClippingColor->setProperty(PLANES_COLOR_KEY, color_.name( ) );
+    _frameClippingColor->setStyleSheet( "background-color: " + color_.name( ));
+    _frameClippingColor->setProperty( PLANES_COLOR_KEY , color_.name( ));
   }
 
-  void MainWindow::sendZeroEQPlaybackOperation(const unsigned int op)
+  void MainWindow::sendZeroEQPlaybackOperation( const unsigned int op )
   {
 #ifdef SIMIL_USE_ZEROEQ
     try
     {
       auto eventMgr = _openGLWidget->player( )->zeqEvents( );
-      if(eventMgr)
+      if ( eventMgr )
       {
-        eventMgr->sendPlaybackOp( static_cast<zeroeq::gmrv::PlaybackOperation>(op) );
+        eventMgr->sendPlaybackOp(
+          static_cast<zeroeq::gmrv::PlaybackOperation>(op));
       }
     }
-    catch(const std::exception &e)
+    catch ( const std::exception& e )
     {
-      std::cerr << "Exception when sending play operation. " << e.what() << __FILE__ << ":" << __LINE__ << std::endl;
+      std::cerr << "Exception when sending play operation. " << e.what( )
+                << __FILE__ << ":" << __LINE__ << std::endl;
     }
-    catch(...)
+    catch ( ... )
     {
-      std::cerr << "Unknown exception when sending play operation. " << __FILE__ << ":" << __LINE__  << std::endl;
+      std::cerr << "Unknown exception when sending play operation. " << __FILE__
+                << ":" << __LINE__ << std::endl;
     }
 #else
     __attribute__((unused)) const auto unused = op; // c++17 [[maybe_unused]]
diff --git a/visimpl/MainWindow.h b/visimpl/MainWindow.h
index 3dab59eebf2e816e61fd2aa65da12f4f7efe1371..e46280ecbcecf2af2b3cd5f1c384795f65ab7d09 100644
--- a/visimpl/MainWindow.h
+++ b/visimpl/MainWindow.h
@@ -41,17 +41,27 @@
 #include <memory>
 
 class Recorder;
+
 class QDockWidget;
+
 class QPushButton;
+
 class QSlider;
+
 class QTimer;
+
 class QRadioButton;
+
 class QGroupBox;
+
 class QPushButton;
+
 class QToolBox;
+
 class QCloseEvent;
 
 class LoadingDialog;
+
 class LoaderThread;
 
 namespace Ui
@@ -65,48 +75,56 @@ namespace visimpl
 
   enum TSelectionSource
   {
-    SRC_EXTERNAL = 0,
-    SRC_PLANES,
-    SRC_WIDGET,
+    SRC_EXTERNAL = 0 ,
+    SRC_PLANES ,
+    SRC_WIDGET ,
     SRC_UNDEFINED
   };
 
   class MainWindow
-  : public QMainWindow
+    : public QMainWindow
   {
-    Q_OBJECT
+  Q_OBJECT
 
   public:
-    explicit MainWindow( QWidget* parent = nullptr,
+    explicit MainWindow( QWidget* parent = nullptr ,
                          bool updateOnIdle = true );
+
     virtual ~MainWindow( void );
 
-    void init( const std::string& zeqUri = std::string() );
-    void showStatusBarMessage ( const QString& message );
+    void init( const std::string& zeqUri = std::string( ));
+
+    void showStatusBarMessage( const QString& message );
 
-    void loadData(const simil::TDataType type,
-                  const std::string arg_1,
-                  const std::string arg_2,
-                  const simil::TSimulationType simType = simil::TSimulationType::TSimSpikes,
-                  const std::string &subsetEventFile = std::string());
+    void loadData( const simil::TDataType type ,
+                   const std::string arg_1 ,
+                   const std::string arg_2 ,
+                   const simil::TSimulationType simType = simil::TSimulationType::TSimSpikes ,
+                   const std::string& subsetEventFile = std::string( ));
 
 #ifdef SIMIL_WITH_REST_API
+
     /** \brief Connects and loads data using the given REST connection.
      * \param[in] config REST connection configuration.
      *
      */
-    void loadRESTData(const simil::LoaderRestData::Configuration &config);
+    void loadRESTData( const simil::LoaderRestData::Configuration& config );
+
 #endif
 
   public slots:
 
     void openBlueConfigThroughDialog( void );
+
     void openCSVFilesThroughDialog( void );
+
     void openHDF5ThroughDialog( void );
-    void openRESTThroughDialog();
+
+    void openRESTThroughDialog( );
+
     void openSubsetEventsFileThroughDialog( void );
 
-    void openSubsetEventFile( const std::string& fileName,
+    void openSubsetEventFile( const std::string& fileName ,
                               bool append = false );
 
     void openRecorder( void );
@@ -116,38 +134,53 @@ namespace visimpl
     void dialogAbout( void );
 
     void dialogSelectionManagement( void );
+
     void dialogSubsetImporter( void );
 
     void togglePlaybackDock( void );
+
     void toggleSimConfigDock( void );
+
     void toggleStackVizDock( void );
 
     void UpdateSimulationSlider( float percentage );
+
     void UpdateSimulationColorMapping( void );
+
     void PreviewSimulationColorMapping( void );
+
     void changeEditorColorMapping( void );
+
     void changeEditorSizeFunction( void );
+
     void UpdateSimulationSizeFunction( void );
+
     void PreviewSimulationSizeFunction( void );
 
     void changeEditorSimDeltaTime( void );
+
     void updateSimDeltaTime( void );
 
     void changeEditorSimTimestepsPS( void );
+
     void updateSimTimestepsPS( void );
 
     void setCircuitSizeScaleFactor( vec3 );
+
     vec3 getCircuitSizeScaleFactor( void ) const;
 
     void showInactive( bool show );
 
     void changeCircuitScaleValue( void );
+
     void updateCircuitScaleValue( void );
 
     void changeEditorDecayValue( void );
+
     void updateSimulationDecayValue( void );
 
     void changeEditorStepByStepDuration( void );
+
     void updateSimStepByStepDuration( void );
 
     void AlphaBlendingToggled( void );
@@ -156,36 +189,52 @@ namespace visimpl
 
     void updateSelectedStatsPickingSingle( unsigned int selected );
 
-    void clippingPlanesActive ( int state );
+    void clippingPlanesActive( int state );
 
     void PlayPause( bool notify = true );
+
     void Play( bool notify = true );
+
     void Pause( bool notify = true );
+
     void Stop( bool notify = true );
+
     void Repeat( bool notify = true );
+
     void PlayAtPosition( bool notify = true );
-    void PlayAtPosition( int, bool notify = true );
-    void PlayAtPercentage( float, bool notify = true );
-    void PlayAtTime( float, bool notify = true);
+
+    void PlayAtPosition( int , bool notify = true );
+
+    void PlayAtPercentage( float , bool notify = true );
+
+    void PlayAtTime( float , bool notify = true );
+
     void requestPlayAt( float );
+
     void PreviousStep( bool notify = true );
+
     void NextStep( bool notify = true );
 
   protected slots:
+
     void configureComponents( void );
+
     void importVisualGroups( void );
 
-    void addGroupControls( VisualGroup *group, unsigned int index,
+    void addGroupControls( std::shared_ptr< VisualGroup > group ,
+                           unsigned int index ,
                            unsigned int size );
+
     void clearGroups( void );
 
     void addGroupFromSelection( void );
+
     void checkGroupsVisibility( void );
-    void checkAttributeGroupsVisibility( void );
 
     void spinBoxValueChanged( void );
 
     void completedStep( void );
+
     void playAtButtonClicked( void );
 
     void clippingPlanesReset( void );
@@ -195,142 +244,153 @@ namespace visimpl
     /** \brief Updates group selection color.
      *
      */
-    void onGroupColorChanged();
+    void onGroupColorChanged( );
 
     /** \brief Updates group selection color.
      *
      */
-    void onGroupPreview();
+    void onGroupPreview( );
 
     /** \brief Shows the dialog to change the group name.
      *
      */
-    void onGroupNameClicked();
+    void onGroupNameClicked( );
 
     /** \brief Removes the group.
      *
      */
-    void onGroupDeleteClicked();
+    void onGroupDeleteClicked( );
 
     /** \brief Removes the visual group with the given index.
-     * param[in] idx Index of visual group in domain manager.
+     * \param[in] name Name of the group to remove.
      *
      */
-    void removeVisualGroup(const unsigned int idx);
+    void removeVisualGroup(const QString &name );
 
     void selectionManagerChanged( void );
-    void setSelection( const GIDUSet& selection_, TSelectionSource source_ = SRC_UNDEFINED );
+
+    void setSelection( const GIDUSet& selection_ ,
+                       TSelectionSource source_ = SRC_UNDEFINED );
+
     void clearSelection( void );
+
     void selectionFromPlanes( void );
 
     /** \brief Executed when OpenGlWidget reports finished loading data.
      *
      */
-    void onDataLoaded();
+    void onDataLoaded( );
 
     /** \brief Loads groups and its properties from a file on disk.
      *
      */
-    void loadGroups();
+    void loadGroups( );
 
     /** \brief Saves current groups and its properties to a file on disk.
      *
      */
-    void saveGroups();
+    void saveGroups( );
 
     /** \brief Enables/disables the toolbar buttons related to stackviz widget.
      * \param[in] status True to enable and false to disable.
      *
      */
-    void changeStackVizToolbarStatus(bool status);
+    void changeStackVizToolbarStatus( bool status );
 
     /** \brief Updates the UI after a recording has finished.
      *
      */
-    void finishRecording();
+    void finishRecording( );
 
     /** \brief Loads camera positions from a file.
      *
      */
-    void loadCameraPositions();
+    void loadCameraPositions( );
 
     /** \brief Saves camera positions to a file on disk.
      *
      */
-    void saveCameraPositions();
+    void saveCameraPositions( );
 
     /** \brief Stores current camera position in the positions list.
      *
      */
-    void addCameraPosition();
+    void addCameraPosition( );
 
     /** \brief Lets the user select a position to remove from the positions list.
      *
      */
-    void removeCameraPosition();
+    void removeCameraPosition( );
 
     /** \brief Changes the camera position to the one specified by the user.
      *
      */
-    void applyCameraPosition();
+    void applyCameraPosition( );
 
     /** \brief Shows a dialog with REST API options and applies them.
      *
      */
-    void configureREST();
+    void configureREST( );
 
     /** \brief Updates the color of the clipping planes color button.
      *
      */
-    void changePlanesColor( const QColor & );
+    void changePlanesColor( const QColor& );
 
   protected:
     void _initSimControlDock( void );
+
     void _initPlaybackDock( void );
+
     void _initStackVizDock( void );
+
     void _initSummaryWidget( void );
 
     void _configurePlayer( void );
+
     void _resetClippingParams( void );
 
     void _updateSelectionGUI( void );
 
-    bool _showDialog( QColor& current, const QString& message = "" );
+    bool _showDialog( QColor& current , const QString& message = "" );
 
     /** \brief Helper to update a group representations colors.
-     * \param[in] idx Index of group in group list.
+     * \param[in] name the name of the group.
      * \param[in] t Transfer function.
      * \param[in] s Size function.
      *
      */
-    void updateGroupColors(size_t idx, const TTransferFunction &t, const TSizeFunction &s);
+    void updateGroupColors( std::string name , const TTransferFunction& t ,
+                            const TSizeFunction& s );
 
-    virtual void closeEvent(QCloseEvent *e) override;
+    virtual void closeEvent( QCloseEvent* e ) override;
 
     /** \brief Closes the data loading dialog.
      *
      */
-    void closeLoadingDialog();
+    void closeLoadingDialog( );
 
-  #ifdef VISIMPL_USE_ZEROEQ
-  #ifdef VISIMPL_USE_GMRVLEX
+#ifdef VISIMPL_USE_ZEROEQ
+#ifdef VISIMPL_USE_GMRVLEX
 
   protected slots:
+
     void ApplyPlaybackOperation( unsigned int playbackOp );
+
     void _zeqEventRepeat( bool repeat );
 
-  #endif
+#endif
 
   protected:
     void _onSelectionEvent( lexis::data::ConstSelectedIDsPtr );
 
-  #endif // VISIMPL_USE_ZEROEQ
+#endif // VISIMPL_USE_ZEROEQ
 
     /** \brief Wrapper aroung player operations to catch exceptions.
      * \param[in] op ZeroEQ Operation identifier.
      *
      */
-    void sendZeroEQPlaybackOperation(const unsigned int op);
+    void sendZeroEQPlaybackOperation( const unsigned int op );
 
 
     Ui::MainWindow* _ui;
@@ -359,20 +419,23 @@ namespace visimpl
     QDockWidget* _simConfigurationDock;
 
     QDockWidget* _stackVizDock;
-    StackViz *_stackViz;
+    StackViz* _stackViz;
 
     QTabWidget* _modeSelectionWidget;
     QToolBox* _toolBoxOptions;
 
-    DataInspector * _objectInspectorGB;
+    DataInspector* _objectInspectorGB;
 
     QGroupBox* _groupBoxTransferFunction;
     TransferFunctionWidget* _tfWidget;
     SelectionManagerWidget* _selectionManager;
     SubsetImporter* _subsetImporter;
 
-    enum TGroupRow { gr_container = 0, gr_checkbox };
-    typedef std::tuple< QWidget*, QCheckBox* > tGroupRow;
+    enum TGroupRow
+    {
+      gr_container = 0 , gr_checkbox
+    };
+    typedef std::tuple< QWidget* , QCheckBox* > tGroupRow;
 
     bool _autoNameGroups;
     QVBoxLayout* _groupLayout;
@@ -420,7 +483,7 @@ namespace visimpl
 
     Recorder* _recorder; /** Recorder */
 
-    std::shared_ptr<LoaderThread> m_loader; /** data loader thread. */
-    LoadingDialog *m_loaderDialog;          /** data loader dialog. */
+    std::shared_ptr< LoaderThread > m_loader; /** data loader thread. */
+    LoadingDialog* m_loaderDialog;          /** data loader dialog. */
   };
 } // namespace visimpl
diff --git a/visimpl/OldDomainManager.cpp b/visimpl/OldDomainManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c4481d57a6419755308ad6237a8b3fdbda4ab91e
--- /dev/null
+++ b/visimpl/OldDomainManager.cpp
@@ -0,0 +1,1374 @@
+/*
+ * Copyright (c) 2015-2020 VG-Lab/URJC.
+ *
+ * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
+ *
+ * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License version 3.0 as published
+ * by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+// ViSimpl
+#include "OldDomainManager.h"
+#include "VisualGroup.h"
+
+// Prefr
+#include "prefr/UpdaterStaticPosition.h"
+#include "prefr/SourceMultiPosition.h"
+
+// C++
+#include <exception>
+
+namespace visimpl
+{
+  void expandBoundingBox( glm::vec3& minBounds ,
+                          glm::vec3& maxBounds ,
+                          const glm::vec3& position )
+  {
+    for ( const auto i: { 0 , 1 , 2 } )
+    {
+      minBounds[ i ] = std::min( minBounds[ i ] , position[ i ] );
+      maxBounds[ i ] = std::max( maxBounds[ i ] , position[ i ] );
+    }
+  }
+
+  constexpr float invRGBInt = 1.0f / 255;
+
+  static std::unordered_map< std::string , std::string > _attributeNameLabels =
+    {
+      { "PYR" , "Pyramidal" } ,
+      { "INT" , "Interneuron" } ,
+      { "EXC" , "Excitatory" } ,
+      { "INH" , "Inhibitory" }
+    };
+
+
+  OldDomainManager::OldDomainManager( const TGIDSet& gids )
+    : _particleSystem( particleSystem )
+    , _gids( gids )
+    , _clusterSelected( )
+    , _clusterUnselected( )
+    , _clusterHighlighted( )
+    , _currentAttrib( T_TYPE_UNDEFINED )
+    , _modelBase( nullptr )
+    , _modelOff( nullptr )
+    , _modelHighlighted( nullptr )
+    , _mode( TMODE_SELECTION )
+    , _decayValue( 0.0f )
+    , _showInactive( true )
+    , _groupByName( false )
+    , _autoGroupByName( true )
+  {
+  }
+
+  void OldDomainManager::init( const tGidPosMap& positions
+#ifdef SIMIL_USE_BRION
+    , const brion::BlueConfig* blueConfig
+#endif
+                             )
+  {
+    _gidPositions = positions;
+
+#ifdef SIMIL_USE_BRION
+    if ( blueConfig )
+      _gidTypes = _loadNeuronTypes( *blueConfig );
+#endif
+
+    std::vector< NeuronParticle > particles;
+    for ( const auto& item: positions )
+    {
+      NeuronParticle p;
+      p.position = item.second;
+      p.life = 0;
+      particles.push_back( p );
+    }
+
+    _clusterSelected.setParticles( particles );
+
+    _loadPaletteColors( );
+  }
+
+  void
+  OldDomainManager::initializeParticleSystem( prefr::IGLRenderProgram* program )
+  {
+    std::cout << "Initializing particle system..." << std::endl;
+
+    _updater = new UpdaterStaticPosition( );
+
+    prefr::Sorter* sorter = new prefr::Sorter( );
+    prefr::OIGLRenderer* renderer = new prefr::OIGLRenderer( program );
+
+    _particleSystem->addUpdater( _updater );
+    _particleSystem->sorter( sorter );
+    _particleSystem->renderer( renderer );
+
+    _modelOff = new prefr::ColorOperationModel( _decayValue , _decayValue );
+    _modelOff->color.Insert( 0.0f , ( glm::vec4( 0.1f , 0.1f , 0.1f , 0.2f )));
+
+    _modelOff->velocity.Insert( 0.0f , 0.0f );
+
+    _modelOff->size.Insert( 1.0f , 10.0f );
+
+    _particleSystem->addModel( _modelOff );
+
+    _modelHighlighted = new prefr::ColorOperationModel( _decayValue ,
+                                                        _decayValue );
+    _modelHighlighted->color.Insert( 0.0f ,
+                                     ( glm::vec4( 0.9f , 0.9f , 0.9f , 0.5f )));
+    _modelHighlighted->color.Insert( 1.0f , ( glm::vec4( 0.75f , 0.75f , 0.75f ,
+                                                         0.2f )));
+    _modelHighlighted->velocity.Insert( 0.0f , 0.0f );
+    _modelHighlighted->size.Insert( 0.0f , 20.0f );
+    _modelHighlighted->size.Insert( 1.0f , 10.0f );
+    _particleSystem->addModel( _modelHighlighted );
+
+
+    _modelBase = new prefr::ColorOperationModel( _decayValue , _decayValue );
+    _modelBase->color.Insert( 0.0f , ( glm::vec4( 0.f , 1.f , 0.f , 0.2 )));
+    _modelBase->color.Insert( 0.35f , ( glm::vec4( 1 , 0 , 0 , 0.5 )));
+    _modelBase->color.Insert( 0.7f , ( glm::vec4( 1.f , 1.f , 0 , 0.5 )));
+    _modelBase->color.Insert( 1.0f , ( glm::vec4( 0 , 0 , 1.f , 0.5 )));
+
+    _modelBase->velocity.Insert( 0.0f , 0.0f );
+
+    _modelBase->size.Insert( 0.0f , 20.0f );
+    _modelBase->size.Insert( 1.0f , 10.0f );
+
+    _particleSystem->addModel( _modelBase );
+
+    _sampler = new prefr::PointSampler( );
+
+    _particleSystem->renderDeadParticles( true );
+    _particleSystem->parallel( true );
+
+    _particleSystem->start( );
+  }
+
+  const tGidPosMap& OldDomainManager::positions( void ) const
+  {
+    return _gidPositions;
+  }
+
+  void OldDomainManager::reloadPositions( void )
+  {
+    if ( _gidToParticle.empty( )) return;
+
+    _resetBoundingBox( );
+
+    auto expandBB = [ this ](
+      const std::pair< unsigned int , unsigned int >& gidPartId )
+    {
+      const auto pos = _gidPositions.find( gidPartId.first );
+
+      auto particle = _particleSystem->particles( ).at( gidPartId.second );
+      particle.set_position( pos->second );
+
+      expandBoundingBox( _boundingBox.first ,
+                         _boundingBox.second ,
+                         pos->second );
+    };
+    std::for_each( _gidToParticle.cbegin( ) , _gidToParticle.cend( ) ,
+                   expandBB );
+  }
+
+  const TGIDSet& OldDomainManager::gids( void ) const
+  {
+    return _gids;
+  }
+
+  void OldDomainManager::mode( const tVisualMode newMode )
+  {
+    clearView( );
+
+    _mode = newMode;
+
+    switch ( _mode )
+    {
+      case TMODE_SELECTION:
+        _generateSelectionIndices( );
+        break;
+      case TMODE_GROUPS:
+        _generateGroupsIndices( );
+        break;
+      case TMODE_ATTRIBUTE:
+        generateAttributesGroups( _currentAttrib == T_TYPE_UNDEFINED ?
+                                  T_TYPE_MORPHO : _currentAttrib );
+
+        _generateAttributesIndices( );
+        break;
+      default:
+      {
+        const auto message = std::string( "Invalid tVisualMode value " ) +
+                             std::to_string( static_cast<int>(newMode)) + " " +
+                             std::string( __FILE__ ) + ":" +
+                             std::to_string( __LINE__ );
+        throw std::out_of_range( message.c_str( ));
+      }
+        break;
+    }
+  }
+
+  tVisualMode OldDomainManager::mode( void ) const
+  {
+    return _mode;
+  }
+
+  void OldDomainManager::clearView( void )
+  {
+    switch ( _mode )
+    {
+      case TMODE_SELECTION:
+        _clearSelectionView( );
+        break;
+      case TMODE_GROUPS:
+        _clearGroupsView( );
+        break;
+      case TMODE_ATTRIBUTE:
+        _clearAttribView( );
+        break;
+      default:
+      {
+        const auto message = std::string( "Invalid tVisualMode value " ) +
+                             std::to_string( static_cast<int>(_mode)) + " " +
+                             std::string( __FILE__ ) + ":" +
+                             std::to_string( __LINE__ );
+        throw std::out_of_range( message.c_str( ));
+      }
+        break;
+    }
+  }
+
+  void OldDomainManager::_clearParticlesReference( void )
+  {
+    _gidToParticle.clear( );
+    _particleToGID.clear( );
+
+    _gidSource.clear( );
+  }
+
+  void OldDomainManager::_clearSelectionView( void )
+  {
+    if ( _sourceSelected )
+      _particleSystem->detachSource( _sourceSelected );
+
+    _clearParticlesReference( );
+  }
+
+  void OldDomainManager::_clearGroupsView( void )
+  {
+    for ( auto group: _groups )
+    {
+      _clearGroup( group , false );
+    }
+
+    _clearParticlesReference( );
+  }
+
+  void OldDomainManager::_clearAttribView( void )
+  {
+    for ( auto group: _attributeGroups )
+    {
+      _clearGroup( group , false );
+    }
+
+    _clearParticlesReference( );
+  }
+
+  void OldDomainManager::_clearGroups( void )
+  {
+    for ( auto group: _groups )
+      delete group;
+
+    _groups.clear( );
+  }
+
+  void OldDomainManager::_clearAttribs( bool clearCustom )
+  {
+    if ( clearCustom )
+    {
+      for ( auto group: _attributeGroups )
+        delete group;
+
+      _attributeGroups.clear( );
+    }
+    else
+    {
+      std::vector< VisualGroup* > aux;
+      aux.reserve( _attributeGroups.size( ));
+      for ( auto group: _attributeGroups )
+        if ( group->custom( ))
+          aux.push_back( group );
+        else
+          delete group;
+      aux.shrink_to_fit( );
+      _attributeGroups = aux;
+    }
+  }
+
+  void OldDomainManager::_loadPaletteColors( void )
+  {
+    scoop::ColorPalette palette =
+      scoop::ColorPalette::colorBrewerQualitative(
+        ( scoop::ColorPalette::ColorBrewerQualitative::Set1 ) , 9 );
+
+    auto colors = palette.colors( );
+
+    _paletteColors.clear( );
+
+    for ( auto color: colors )
+    {
+      _paletteColors.emplace_back( generateColorPair( color ));
+    }
+  }
+
+  void OldDomainManager::update( void )
+  {
+    switch ( _mode )
+    {
+      case TMODE_SELECTION:
+        _generateSelectionIndices( );
+        break;
+      case TMODE_GROUPS:
+        _generateGroupsIndices( );
+        break;
+      case TMODE_ATTRIBUTE:
+        _generateAttributesIndices( );
+        break;
+      default:
+      {
+        const auto message = std::string( "Invalid tVisualMode value " ) +
+                             std::to_string( static_cast<int>(_mode)) + " " +
+                             std::string( __FILE__ ) + ":" +
+                             std::to_string( __LINE__ );
+        throw std::out_of_range( message.c_str( ));
+      }
+        break;
+    }
+  }
+
+  void OldDomainManager::updateData( const TGIDSet& gids ,
+                                     const tGidPosMap& positions )
+  {
+    _gids = gids;
+    _gidPositions = positions;
+
+    _sourceSelected->setPositions( _gidPositions );
+    clearView( );
+    update( );
+    reloadPositions( );
+  }
+
+  void OldDomainManager::_resetBoundingBox( void )
+  {
+    _boundingBox.first = glm::vec3( std::numeric_limits< float >::max( ) ,
+                                    std::numeric_limits< float >::max( ) ,
+                                    std::numeric_limits< float >::max( ));
+
+    _boundingBox.second = glm::vec3( std::numeric_limits< float >::min( ) ,
+                                     std::numeric_limits< float >::min( ) ,
+                                     std::numeric_limits< float >::min( ));
+  }
+
+  bool OldDomainManager::showGroups( void )
+  {
+    return _mode == TMODE_GROUPS;
+  }
+
+  void OldDomainManager::updateGroups( void )
+  {
+    _generateGroupsIndices( );
+  }
+
+  void OldDomainManager::updateAttributes( void )
+  {
+    _generateAttributesIndices( );
+  }
+
+  void OldDomainManager::showInactive( bool state )
+  {
+    _showInactive = state;
+  }
+
+  void OldDomainManager::setVisualGroupState( unsigned int i , bool state ,
+                                              bool attrib )
+  {
+    VisualGroup* group = nullptr;
+
+    if ( !attrib )
+    {
+      if ( i < _groups.size( ))
+        group = _groups[ i ];
+    }
+    else
+    {
+      if ( i < _attributeGroups.size( ))
+        group = _attributeGroups[ i ];
+    }
+
+    if ( !group ) return;
+
+    group->active( state );
+    group->cluster( )->setModel( state ? group->model( ) : _modelOff );
+
+    if ( !_showInactive )
+      group->source( )->active( state );
+  }
+
+  void OldDomainManager::_updateGroupsModels( void )
+  {
+    for ( auto group: _groups )
+    {
+      group->model( group->active( ) ? group->model( ) : _modelOff );
+    }
+  }
+
+  void OldDomainManager::_updateSelectionIndices( void )
+  {
+    prefr::ParticleIndices selection;
+    prefr::ParticleIndices other;
+    for ( auto gid: _gids )
+    {
+      auto particleId = _gidToParticle.find( gid )->second;
+
+      if ( _selection.empty( ) || _selection.find( gid ) != _selection.end( ))
+        selection.push_back( particleId );
+      else
+        other.push_back( particleId );
+    }
+    _clusterSelected->particles( ).indices( selection );
+    _clusterUnselected->particles( ).indices( other );
+
+    _clusterSelected->setModel( _modelBase );
+    _clusterUnselected->setModel( _modelOff );
+  }
+
+  void OldDomainManager::_generateSelectionIndices( void )
+  {
+    unsigned int numParticles = _gids.size( );
+
+    prefr::ParticleIndices indices;
+    prefr::ParticleIndices indicesSelected;
+    prefr::ParticleIndices indicesUnselected;
+
+    indices.reserve( numParticles );
+    indicesSelected.reserve( numParticles );
+    indicesUnselected.reserve( numParticles );
+
+    auto availableParticles = _particleSystem->retrieveUnused( numParticles );
+    const auto count = availableParticles.size( );
+    _gidToParticle.reserve( count );
+    _particleToGID.reserve( count );
+    _gidSource.reserve( count );
+
+    _resetBoundingBox( );
+
+    auto gidit = _gids.begin( );
+    for ( auto particle: availableParticles )
+    {
+      const unsigned int id = particle.id( );
+
+      // Create reference
+      _gidToParticle.insert( std::make_pair( *gidit , id ));
+      _particleToGID.insert( std::make_pair( id , *gidit ));
+
+      _gidSource.insert( std::make_pair( *gidit , _sourceSelected ));
+
+      // Check if part of selection
+      if ( _selection.empty( ) ||
+           _selection.find( *gidit ) != _selection.end( ))
+      {
+        indicesSelected.emplace_back( id );
+
+        const auto pos = _gidPositions.find( *gidit )->second;
+        expandBoundingBox( _boundingBox.first , _boundingBox.second , pos );
+      }
+      else
+      {
+        indicesUnselected.emplace_back( id );
+      }
+
+      indices.emplace_back( id );
+
+      ++gidit;
+    }
+
+    indicesSelected.shrink_to_fit( );
+    indicesUnselected.shrink_to_fit( );
+
+    _clusterSelected->particles( ).indices( indicesSelected );
+    _clusterUnselected->particles( ).indices( indicesUnselected );
+
+    _sourceSelected->setIdxTranslation( _particleToGID );
+
+    _particleSystem->addSource( _sourceSelected , indices );
+
+    _clusterSelected->setUpdater( _updater );
+    _clusterUnselected->setUpdater( _updater );
+
+    _clusterUnselected->setModel( _modelOff );
+    _clusterSelected->setModel( _modelBase );
+  }
+
+  VisualGroup* OldDomainManager::_generateGroup( const GIDUSet& gids ,
+                                                 const std::string& name ,
+                                                 unsigned int idx ) const
+  {
+    VisualGroup* group = new VisualGroup( name );
+
+    // Create model from base
+    prefr::ColorOperationModel* model =
+      new prefr::ColorOperationModel( *_modelBase );
+    group->model( model );
+
+    TTransferFunction colorVariation;
+    auto colors = _paletteColors[ idx % _paletteColors.size( ) ];
+    colorVariation.push_back( std::make_pair( 0.0f , colors.first ));
+    colorVariation.push_back( std::make_pair( 1.0f , colors.second ));
+    group->colorMapping( colorVariation );
+
+    prefr::Cluster* cluster = new prefr::Cluster( );
+
+    SourceMultiPosition* source = new SourceMultiPosition( );
+    source->setPositions( _gidPositions );
+    source->setIdxTranslation( _particleToGID );
+
+    group->cluster( cluster );
+    group->source( source );
+
+    group->gids( gids );
+
+    group->active( true );
+    group->cached( false );
+    group->dirty( true );
+
+    return group;
+  }
+
+  VisualGroup*
+  OldDomainManager::addVisualGroupFromSelection( const std::string& name ,
+                                                 bool overrideGIDs )
+  {
+    return addVisualGroup( _selection , name , overrideGIDs );
+  }
+
+  VisualGroup* OldDomainManager::addVisualGroup( const GIDUSet& gids ,
+                                                 const std::string& name ,
+                                                 bool overrideGIDS )
+  {
+    VisualGroup* group = _generateGroup( gids , name , _groups.size( ));
+    group->custom( true );
+
+    if ( overrideGIDS )
+    {
+      for ( auto gid: gids )
+      {
+        auto reference = _neuronGroup.find( gid );
+
+        if ( reference != _neuronGroup.end( ))
+        {
+          auto& oldGroup = reference->second;
+
+          auto oldGroupGIDs = oldGroup->gids( );
+          oldGroupGIDs.erase( gid );
+          reference->second->gids( oldGroupGIDs );
+
+          oldGroup->cached( false );
+        }
+      }
+    }
+    _groups.push_back( group );
+
+    return group;
+  }
+
+  void OldDomainManager::removeVisualGroup( unsigned int i )
+  {
+    auto group = _groups[ i ];
+
+    _clearGroup( group , true );
+
+    delete group;
+
+    _groups.erase( _groups.begin( ) + i );
+  }
+
+  void OldDomainManager::_clearGroup( VisualGroup* group , bool clearState )
+  {
+    _particleSystem->detachSource( group->source( ));
+
+    if ( clearState )
+    {
+      for ( auto gid: group->gids( ))
+      {
+        auto ref = _gidToParticle.find( gid );
+
+        if ( ref != _gidToParticle.end( ))
+        {
+          _particleToGID.erase( ref->second );
+          _gidToParticle.erase( ref );
+        }
+        _neuronGroup.erase( gid );
+      }
+    }
+
+    group->cached( false );
+    group->dirty( true );
+  }
+
+  void OldDomainManager::_generateGroupsIndices( void )
+  {
+    for ( auto group: _groups )
+    {
+      if ( !group->dirty( ) || !group->active( ))
+        continue;
+
+      if ( group->cached( ))
+        _clearGroup( group , true );
+
+      const auto& gids = group->gids( );
+
+      auto availableParticles = _particleSystem->retrieveUnused( gids.size( ));
+
+      auto cluster = group->cluster( );
+
+      _particleSystem->addCluster( cluster , availableParticles.indices( ));
+      _particleSystem->addSource( group->source( ) ,
+                                  availableParticles.indices( ));
+
+      cluster->setUpdater( _updater );
+      cluster->setModel( group->model( ));
+
+      auto partId = availableParticles.begin( );
+      for ( auto gid: gids )
+      {
+        _neuronGroup.insert( std::make_pair( gid , group ));
+
+        _gidToParticle.insert( std::make_pair( gid , partId.id( )));
+        _particleToGID.insert( std::make_pair( partId.id( ) , gid ));
+
+        ++partId;
+      }
+
+      group->cached( true );
+      group->dirty( false );
+    }
+  }
+
+  void OldDomainManager::generateAttributesGroups( tNeuronAttributes attrib )
+  {
+    if ( attrib == _currentAttrib || attrib == T_TYPE_UNDEFINED ||
+         _mode != TMODE_ATTRIBUTE )
+      return;
+
+    _clearAttribView( );
+
+    _clearAttribs( );
+
+    _clearParticlesReference( );
+
+    // Clustering
+    // TODO auto-detect attribute type
+    std::unordered_set< unsigned int > differentValues;
+    std::unordered_multimap< unsigned int , unsigned int > valueGids;
+
+    auto functor = ( [ & ]( const NeuronAttributes& att )
+    {
+      return ( attrib == T_TYPE_MORPHO ) ? ( std::get< T_TYPE_MORPHO >( att )) :
+             std::get< T_TYPE_FUNCTION >( att );
+    } );
+
+    const auto& typeIndices =
+      ( attrib == T_TYPE_MORPHO ) ? _typeToIdxMorpho : _typeToIdxFunction;
+
+    const auto& nameIndices =
+      ( attrib == T_TYPE_MORPHO ) ? _namesIdxMorpho : _namesIdxFunction;
+
+    for ( auto attribs: _gidTypes )
+    {
+      unsigned int gid = attribs.first;
+      unsigned int value = typeIndices.find( functor( attribs.second ))->second;
+
+      differentValues.insert( value );
+      valueGids.insert( std::make_pair( value , gid ));
+    }
+
+    _attributeGroups.resize( nameIndices.size( ));
+
+    // Generate attrib groups
+    for ( auto typeIndex: nameIndices )
+    {
+      GIDUSet gids;
+
+      auto elements = valueGids.equal_range( typeIndex.second );
+      for ( auto it = elements.first; it != elements.second; ++it )
+        gids.insert( it->second );
+
+      auto group = _generateGroup( gids , typeIndex.first , typeIndex.second );
+      group->custom( false );
+
+      _attributeGroups[ typeIndex.second ] = group;
+    }
+
+    _generateAttributesIndices( );
+
+    _currentAttrib = attrib;
+  }
+
+  void OldDomainManager::_generateAttributesIndices( void )
+  {
+    for ( auto group: _attributeGroups )
+    {
+
+      if ( !group->dirty( ))
+        continue;
+
+      if ( group->cached( ))
+        _clearGroup( group , true );
+
+      const auto& gids = group->gids( );
+
+      auto availableParticles = _particleSystem->retrieveUnused( gids.size( ));
+
+      auto cluster = group->cluster( );
+
+      _particleSystem->addCluster( cluster , availableParticles.indices( ));
+      _particleSystem->addSource( group->source( ) ,
+                                  availableParticles.indices( ));
+
+      cluster->setUpdater( _updater );
+      cluster->setModel( group->model( ));
+
+      auto partId = availableParticles.begin( );
+      for ( auto gid: gids )
+      {
+        _neuronGroup.insert( std::make_pair( gid , group ));
+
+        _gidToParticle.insert( std::make_pair( gid , partId.id( )));
+        _particleToGID.insert( std::make_pair( partId.id( ) , gid ));
+
+        ++partId;
+      }
+
+      group->cached( true );
+      group->dirty( false );
+    }
+  }
+
+  void OldDomainManager::processInput( const simil::SpikesCRange& spikes_ ,
+                                       float begin , float end , bool clear )
+  {
+    if ( clear )
+      resetParticles( );
+
+    switch ( _mode )
+    {
+      case TMODE_SELECTION:
+        _processFrameInputSelection( spikes_ , begin , end );
+        break;
+      case TMODE_GROUPS:
+        _processFrameInputGroups( spikes_ , begin , end );
+        break;
+      case TMODE_ATTRIBUTE:
+        _processFrameInputAttributes( spikes_ , begin , end );
+        break;
+      default:
+      {
+        const auto message = std::string( "Invalid tVisualMode value " ) +
+                             std::to_string( static_cast<int>(_mode)) + " " +
+                             std::string( __FILE__ ) + ":" +
+                             std::to_string( __LINE__ );
+        throw std::out_of_range( message.c_str( ));
+      }
+        break;
+    }
+  }
+
+  OldDomainManager::TModifiedNeurons
+  OldDomainManager::_parseInput( const simil::SpikesCRange& spikes_ ,
+                                 float /*begin*/ , float end )
+  {
+    TModifiedNeurons result;
+    std::unordered_map< uint32_t , float > inserted;
+
+    for ( simil::SpikesCIter spike = spikes_.first;
+          spike != spikes_.second; ++spike )
+    {
+      float lifeValue = _decayValue - ( end - spike->first );
+
+      auto it = inserted.find( spike->second );
+      if ( it == inserted.end( ))
+      {
+        inserted[ spike->second ] = lifeValue;
+      }
+    }
+
+    result.reserve( inserted.size( ));
+    for ( auto spike: inserted )
+    {
+      result.emplace_back( spike.first , spike.second );
+    }
+
+    return result;
+  }
+
+  void OldDomainManager::_processFrameInputSelection(
+    const simil::SpikesCRange& spikes_ ,
+    float begin , float end )
+  {
+    if ( !_particleSystem || !_particleSystem->run( ) ||
+         _mode != TMODE_SELECTION )
+      return;
+
+    auto state = _parseInput( spikes_ , begin , end );
+
+    for ( const auto& neuron: state )
+    {
+      auto gid = std::get< 0 >( neuron );
+
+      if ( _selection.empty( ) || _selection.find( gid ) != _selection.end( ))
+      {
+        const auto source = _gidSource.find( gid );
+
+        if ( source == _gidSource.end( ))
+        {
+          std::cout << "GID " << gid << " source not found." << std::endl;
+          return;
+        }
+
+        const unsigned int partIdx = _gidToParticle.find( gid )->second;
+        auto particle = _particleSystem->particles( ).at( partIdx );
+        particle.set_life( std::get< 1 >( neuron ));
+      }
+    }
+  }
+
+  void
+  OldDomainManager::_processFrameInputGroups( const simil::SpikesCRange& spikes_ ,
+                                              float begin , float end )
+  {
+
+    if ( !_particleSystem || !_particleSystem->run( ) || _mode != TMODE_GROUPS )
+      return;
+
+    auto state = _parseInput( spikes_ , begin , end );
+
+    for ( const auto& neuron: state )
+    {
+      auto gid = std::get< 0 >( neuron );
+
+      auto visualGroup = _neuronGroup.find( gid );
+
+      if ( visualGroup != _neuronGroup.end( ) && visualGroup->second->active( ))
+      {
+        auto partIt = _gidToParticle.find( gid );
+        if ( partIt != _gidToParticle.end( ))
+        {
+          unsigned int particleIndex = partIt->second;
+
+          auto particle = _particleSystem->particles( ).at( particleIndex );
+          particle.set_life( std::get< 1 >( neuron ));
+        }
+      }
+    }
+  }
+
+  void OldDomainManager::_processFrameInputAttributes(
+    const simil::SpikesCRange& spikes_ ,
+    float begin , float end )
+  {
+
+    if ( !_particleSystem || !_particleSystem->run( ) ||
+         _mode != TMODE_ATTRIBUTE )
+      return;
+
+    auto state = _parseInput( spikes_ , begin , end );
+
+    for ( const auto& neuron: state )
+    {
+      auto gid = std::get< 0 >( neuron );
+
+      auto visualGroup = _neuronGroup.find( gid );
+
+      if ( visualGroup != _neuronGroup.end( ) && visualGroup->second->active( ))
+      {
+        auto partIt = _gidToParticle.find( gid );
+        if ( partIt != _gidToParticle.end( ))
+        {
+          unsigned int particleIndex = partIt->second;
+          auto particle = _particleSystem->particles( ).at( particleIndex );
+          particle.set_life( std::get< 1 >( neuron ));
+        }
+      }
+    }
+  }
+
+  void OldDomainManager::selection( const GIDUSet& newSelection )
+  {
+    _selection = newSelection;
+
+    if ( _mode == TMODE_SELECTION )
+    {
+      _updateSelectionIndices( );
+    }
+  }
+
+  const GIDUSet& OldDomainManager::selection( void )
+  {
+    return _selection;
+  }
+
+  tBoundingBox OldDomainManager::boundingBox( void ) const
+  {
+    tBoundingBox result = _boundingBox;
+
+    if ( _boundingBox.first == _boundingBox.second )
+    {
+      result.second = _boundingBox.second + vec3( 0.1f , 0.1f , 0.1f );
+    }
+
+    return result;
+  }
+
+  prefr::ColorOperationModel* OldDomainManager::modelSelectionBase( void )
+  {
+    return _modelBase;
+  }
+
+  void OldDomainManager::decay( float decayValue )
+  {
+    _decayValue = decayValue;
+
+    _modelBase->setLife( decayValue , decayValue );
+    _modelHighlighted->setLife( decayValue , decayValue );
+  }
+
+  float OldDomainManager::decay( void ) const
+  {
+    return _decayValue;
+  }
+
+  void OldDomainManager::clearSelection( void )
+  {
+    _selection.clear( );
+
+    if ( _mode == TMODE_SELECTION )
+    {
+      _updateSelectionIndices( );
+    }
+  }
+
+  void OldDomainManager::resetParticles( void )
+  {
+    _particleSystem->run( false );
+
+    auto particles = _particleSystem->retrieveActive( );
+    for ( int i = 0; i < static_cast<int>( particles.size( )); ++i )
+    {
+      particles.at( i ).set_life( 0 );
+    }
+
+    _particleSystem->run( true );
+
+    _particleSystem->update( 0.0f );
+  }
+
+  const std::vector< VisualGroup* >& OldDomainManager::groups( void ) const
+  {
+    return _groups;
+  }
+
+  const std::vector< VisualGroup* >&
+  OldDomainManager::attributeGroups( void ) const
+  {
+    return _attributeGroups;
+  }
+
+  const std::vector< std::pair< QColor , QColor >>&
+  OldDomainManager::paletteColors( void ) const
+  {
+    return _paletteColors;
+  }
+
+  const std::vector< std::string >& OldDomainManager::namesMorpho( void ) const
+  {
+    return _namesTypesMorpho;
+  }
+
+  const std::vector< std::string >& OldDomainManager::namesFunction( void ) const
+  {
+    return _namesTypesFunction;
+  }
+
+  std::pair< QColor , QColor > OldDomainManager::generateColorPair(
+    scoop::Color& color )
+  {
+    constexpr float brightFactor = 0.4f;
+    constexpr float darkFactor = 1.0f - brightFactor;
+
+    const glm::vec4 baseColor( color.red( ) * invRGBInt ,
+                               color.green( ) * invRGBInt ,
+                               color.blue( ) * invRGBInt , 0.6f );
+
+    color = QColor( baseColor.r * 255 ,
+                    baseColor.g * 255 ,
+                    baseColor.b * 255 ,
+                    baseColor.a * 255 );
+
+    const glm::vec4 darkColor =
+      ( baseColor * brightFactor ) +
+      ( glm::vec4( 0.1f , 0.1f , 0.1f , 0.4f ) * darkFactor );
+
+    const QColor darkqColor = QColor( darkColor.r * 255 ,
+                                      darkColor.g * 255 ,
+                                      darkColor.b * 255 ,
+                                      darkColor.a * 255 );
+
+    return std::make_pair( color , darkqColor );
+  }
+
+#ifdef SIMIL_USE_BRION
+
+  tNeuronAttribs
+  OldDomainManager::_loadNeuronTypes( const brion::BlueConfig& blueConfig )
+  {
+    tNeuronAttribs result;
+
+    const auto& gids = _gids;
+
+    try
+    {
+      brion::Circuit circuit( blueConfig.getCircuitSource( ));
+
+      uint32_t attributes = brion::NEURON_COLUMN_GID |
+                            brion::NEURON_MTYPE |
+                            brion::NEURON_ETYPE;
+
+
+      const brion::NeuronMatrix& attribsData = circuit.get( gids , attributes );
+
+      _namesTypesMorpho = circuit.getTypes(
+        brion::NEURONCLASS_MORPHOLOGY_CLASS );
+      _namesTypesFunction = circuit.getTypes(
+        brion::NEURONCLASS_FUNCTION_CLASS );
+
+      _typesMorpho.reserve( gids.size( ));
+      _typesFunction.reserve( gids.size( ));
+
+      for ( unsigned int i = 0; i < gids.size( ); ++i )
+      {
+        const unsigned int morphoType =
+          boost::lexical_cast< unsigned int >( attribsData[ i ][ 1 ] );
+
+        const unsigned int functionType =
+          boost::lexical_cast< unsigned int >( attribsData[ i ][ 2 ] );
+
+        _typesMorpho.push_back( morphoType );
+        _typesFunction.push_back( functionType );
+      }
+
+    }
+    catch ( ... )
+    {
+      brain::Circuit circuit( blueConfig );
+      _namesTypesMorpho = circuit.getMorphologyTypeNames( );
+      _namesTypesFunction = circuit.getElectrophysiologyTypeNames( );
+
+      auto transform = [ ]( const std::vector< size_t >& vec )
+      {
+        std::vector< unsigned long > vec32;
+        vec32.reserve( vec.size( ));
+
+        std::for_each( vec.cbegin( ) , vec.cend( ) ,
+                       [ &vec32 ]( const size_t num )
+                       {
+                         vec32.emplace_back( static_cast<unsigned long>(num));
+                       } );
+
+        return vec32;
+      };
+
+      _typesMorpho = transform( circuit.getMorphologyTypes( gids ));
+      _typesFunction = transform( circuit.getElectrophysiologyTypes( gids ));
+
+    }
+
+    unsigned int counter = 0;
+
+    for ( auto gid: gids )
+    {
+      NeuronAttributes attribs;
+
+      for ( unsigned int i = 0; i < ( unsigned int ) T_TYPE_UNDEFINED; ++i )
+      {
+        unsigned int typeValue =
+          (( i == 0 ) ? _typesMorpho : _typesFunction )[ counter ];
+
+        auto& stats = (( i == 0 ) ? _statsMorpho : _statsFunction );
+
+        auto& indexBack =
+          ( i == 0 ) ? _idxToTypeMorpho : _idxToTypeFunction;
+
+        auto attribFunctor =
+          ( i == 0 ) ? &std::get< T_TYPE_MORPHO >( attribs ) :
+          &std::get< T_TYPE_FUNCTION >( attribs );
+
+        auto statsIt = stats.find( typeValue );
+        if ( statsIt == stats.end( ))
+          statsIt = stats.insert( std::make_pair( typeValue , 0 )).first;
+
+        ++statsIt->second;
+
+        indexBack.insert( std::make_pair( i , typeValue ));
+
+        *attribFunctor = typeValue;
+      }
+
+      ++counter;
+
+      result.insert( std::make_pair( gid , attribs ));
+    }
+
+
+    if ( _autoGroupByName )
+    {
+      for ( unsigned int i = 0; i < ( unsigned int ) T_TYPE_UNDEFINED; ++i )
+      {
+        const auto& names = ( i == 0 ) ? _namesTypesMorpho
+                                       : _namesTypesFunction;
+        auto& groupedNameStorage =
+          ( i == 0 ) ? _namesTypesMorphoGrouped : _namesTypesFunctionGrouped;
+
+        auto& groupedIndices =
+          ( i == 0 ) ? _typeToIdxMorpho : _typeToIdxFunction;
+
+        auto& nameIndexer = ( i == 0 ) ? _namesIdxMorpho : _namesIdxFunction;
+
+        const auto& stats = (( i == 0 ) ? _statsMorpho : _statsFunction );
+
+        counter = 0;
+        for ( auto name: names )
+        {
+
+          if ( stats.find( counter ) != stats.end( ))
+          {
+
+            auto nameIndex = nameIndexer.find( name );
+            if ( nameIndex == nameIndexer.end( ))
+            {
+              unsigned int index = nameIndexer.size( );
+              nameIndex = nameIndexer.insert(
+                std::make_pair( name , index )).first;
+            }
+
+            groupedIndices.insert(
+              std::make_pair( counter , nameIndex->second ));
+          }
+
+          ++counter;
+
+        }
+        std::cout << std::endl;
+
+        groupedNameStorage.resize( nameIndexer.size( ));
+
+        for ( auto name: nameIndexer )
+        {
+          groupedNameStorage[ name.second ] = name.first;
+        }
+
+        if ( groupedNameStorage.size( ) != names.size( ))
+          _groupByName = true;
+      }
+    }
+
+//    std::cout << "Loaded attributes." << std::endl;
+//    std::cout << "- Morphological: " << std::endl;
+//    for( auto type : _statsMorpho )
+//      std::cout << _namesTypesMorpho[ type.first ]
+//                << " -> " << type.first
+//                << " # " << type.second
+//                << std::endl;
+//
+//    std::cout << " Grouped in: " << std::endl;
+//    for( auto type : _namesIdxMorpho )
+//      std::cout << type.second << ": " << type.first << std::endl;
+//
+//    std::cout << "- Functional: " << std::endl;
+//    for( auto type : _statsFunction )
+//      std::cout << _namesTypesFunction[ type.first ]
+//                << " -> " << type.first
+//                << " # " << type.second
+//                << std::endl;
+//
+//    std::cout << " Grouped in: " << std::endl;
+//    for( auto type : _namesIdxFunction )
+//      std::cout << type.second << ": " << type.first << std::endl;
+
+    return result;
+  }
+
+#endif // SIMIL_USE_BRION
+
+  const std::vector< long unsigned int >&
+  OldDomainManager::attributeValues( int attribNumber ) const
+  {
+    if (( tNeuronAttributes ) attribNumber == T_TYPE_MORPHO )
+      return _typesMorpho;
+    else
+      return _typesFunction;
+  }
+
+  Strings OldDomainManager::attributeNames( int attribNumber , bool ) const
+  {
+    Strings result;
+
+    if ( _groupByName )
+    {
+      result = ( attribNumber == 0 ) ? _namesTypesMorphoGrouped :
+               _namesTypesFunctionGrouped;
+    }
+    else
+    {
+      const auto& namesIdx = ( attribNumber == 0 ) ? _namesIdxMorpho
+                                                   : _namesIdxFunction;
+
+      result.resize( namesIdx.size( ));
+
+      for ( auto name: namesIdx )
+      {
+        result[ name.second ] = name.first;
+      }
+
+    }
+    result.shrink_to_fit( );
+
+    return result;
+  }
+
+  tAppStats OldDomainManager::attributeStatistics( void ) const
+  {
+    tAppStats result;
+
+    const auto& stats =
+      ( _currentAttrib == T_TYPE_MORPHO ) ? _statsMorpho : _statsFunction;
+
+    const auto& typeIdx =
+      ( _currentAttrib == T_TYPE_MORPHO ) ? &_typeToIdxMorpho
+                                          : &_typeToIdxFunction;
+
+    const auto& nameIndices =
+      ( _currentAttrib == T_TYPE_MORPHO ) ? _namesIdxMorpho : _namesIdxFunction;
+
+    unsigned int numberOfValues = nameIndices.size( );
+
+    result.resize( numberOfValues );
+
+    std::vector< unsigned int > statsTotal( numberOfValues , 0 );
+
+    for ( auto valueStats: stats )
+    {
+      unsigned int index = typeIdx->find( valueStats.first )->second;
+
+      statsTotal[ index ] += valueStats.second;
+    }
+
+    for ( auto attrib: nameIndices )
+    {
+      auto& name = attrib.first;
+
+      auto idxIt = nameIndices.find( name );
+      unsigned int idx = idxIt->second;
+
+      unsigned int value = statsTotal[ idx ];
+
+      std::string label = "";
+      auto labelIt = _attributeNameLabels.find( name );
+      if ( labelIt != _attributeNameLabels.end( ))
+        label = labelIt->second;
+
+      tStatsGroup attribs = std::make_tuple( 0 , name , label , value );
+
+      result[ idx ] = attribs;
+    }
+
+    return result;
+  }
+
+  tParticleInfo
+  OldDomainManager::pickingInfoSimple( unsigned int particleId ) const
+  {
+    tParticleInfo result;
+
+    unsigned int gid = 0;
+    bool valid = false;
+    vec3 position( 0 , 0 , 0 );
+    QPoint screenPos( 0 , 0 );
+
+    auto gidIt = _particleToGID.find( particleId );
+    if ( gidIt != _particleToGID.end( ))
+    {
+      gid = gidIt->second;
+
+      auto particle = _particleSystem->particles( ).at( particleId );
+
+      position = particle.position( );
+
+      valid = true;
+    }
+
+    std::get< T_PART_GID >( result ) = gid;
+    std::get< T_PART_INTERNAL_GID >( result ) = particleId;
+    std::get< T_PART_POSITION >( result ) = position;
+    std::get< T_PART_SCREEN_POS >( result ) = screenPos;
+    std::get< T_PART_VALID >( result ) = valid;
+
+    return result;
+  }
+
+  void OldDomainManager::highlightElements(
+    const std::unordered_set< unsigned int >& highlighted )
+  {
+    clearHighlighting( );
+
+    prefr::ParticleIndices indices;
+    indices.reserve( highlighted.size( ));
+
+    for ( auto gid: highlighted )
+      indices.push_back( gid );
+
+    _clusterHighlighted->particles( ).indices( indices );
+
+    _clusterHighlighted->setModel( _modelHighlighted );
+
+  }
+
+  void OldDomainManager::clearHighlighting( void )
+  {
+    if ( _mode == TMODE_SELECTION )
+    {
+      _clusterSelected->setModel( _modelBase );
+      _clusterUnselected->setModel( _modelOff );
+    }
+    else
+    {
+      auto groupArray = ( _mode == TMODE_GROUPS ) ? _groups : _attributeGroups;
+
+      for ( auto group: groupArray )
+      {
+        group->cluster( )->setModel( group->model( ));
+      }
+    }
+  }
+}
diff --git a/visimpl/OldDomainManager.h b/visimpl/OldDomainManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb3659cfb81329d202a9546e9740b296236cf09a
--- /dev/null
+++ b/visimpl/OldDomainManager.h
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2015-2020 VG-Lab/URJC.
+ *
+ * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
+ *
+ * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License version 3.0 as published
+ * by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef __VISIMPL_VISUALGROUPMANAGER__
+#define __VISIMPL_VISUALGROUPMANAGER__
+
+#include <unordered_map>
+
+#include <prefr/prefr.h>
+#include <prefr/GL/IGLRenderProgram.h>
+#include <simil/simil.h>
+#include <scoop/scoop.h>
+
+#include <sumrice/sumrice.h>
+
+#include "types.h"
+#include "VisualGroup.h"
+#include "visimpl/particlelab/ColorOperationModel.h"
+#include "prefr/SourceMultiPosition.h"
+
+namespace visimpl
+{
+  enum tVisualMode
+  {
+    TMODE_SELECTION = 0 ,
+    TMODE_GROUPS ,
+    TMODE_ATTRIBUTE ,
+    TMODE_UNDEFINED
+  };
+
+  class OldDomainManager
+  {
+  public:
+
+    OldDomainManager( const TGIDSet& gids );
+
+#ifdef SIMIL_USE_BRION
+
+    void
+    init( const tGidPosMap& positions , const brion::BlueConfig* blueConfig );
+
+#else
+    void init( const tGidPosMap& positions );
+#endif
+
+
+    void initializeParticleSystem( prefr::IGLRenderProgram* program );
+
+    VisualGroup* addVisualGroupFromSelection( const std::string& name ,
+                                              bool overrideGIDs = false );
+
+    VisualGroup*
+    addVisualGroup( const GIDUSet& group_ , const std::string& name ,
+                    bool overrideGIDs = false );
+
+    void
+    setVisualGroupState( unsigned int i , bool state , bool attrib = false );
+
+    void removeVisualGroup( unsigned int i );
+
+    void showInactive( bool state );
+
+
+    void generateAttributesGroups( tNeuronAttributes attrib );
+
+    void processInput( const simil::SpikesCRange& spikes_ ,
+                       float begin , float end , bool clear );
+
+    void update( void );
+
+    void updateData( const TGIDSet& gids , const tGidPosMap& positions );
+
+    void mode( const tVisualMode newMode );
+
+    tVisualMode mode( void ) const;
+
+    void clearView( void );
+
+    bool showGroups( void );
+
+    void updateGroups( void );
+
+    void updateAttributes( void );
+
+    void selection( const GIDUSet& newSelection );
+
+    const GIDUSet& selection( void );
+
+    void decay( float decayValue );
+
+    float decay( void ) const;
+
+    void clearSelection( void );
+
+    void resetParticles( void );
+
+    const std::vector< VisualGroup* >& groups( void ) const;
+
+    const std::vector< VisualGroup* >& attributeGroups( void ) const;
+
+    const tGidPosMap& positions( void ) const;
+
+    void reloadPositions( void );
+
+
+    const TGIDSet& gids( void ) const;
+
+    tBoundingBox boundingBox( void ) const;
+
+    prefr::ColorOperationModel* modelSelectionBase( void );
+
+    const std::vector< std::pair< QColor , QColor >>&
+    paletteColors( void ) const;
+
+    // Statistics
+    const std::vector< std::string >& namesMorpho( void ) const;
+
+    const std::vector< std::string >& namesFunction( void ) const;
+
+    const std::vector< long unsigned int >&
+    attributeValues( int attribNumber ) const;
+
+    Strings attributeNames( int attribNumber , bool labels = false ) const;
+
+    tAppStats attributeStatistics( void ) const;
+
+    tParticleInfo pickingInfoSimple( unsigned int particleId ) const;
+
+    void
+    highlightElements( const std::unordered_set< unsigned int >& highlighted );
+
+    void clearHighlighting( void );
+
+    /** \brief Helper method to generate que QColor pair from a given color.
+     * \param[inout] c scoop::Color object reference.
+     *
+     */
+    static std::pair< QColor , QColor > generateColorPair( scoop::Color& c );
+
+  protected:
+
+    typedef std::vector< std::tuple< uint32_t , float >> TModifiedNeurons;
+
+    TModifiedNeurons _parseInput( const simil::SpikesCRange& spikes_ ,
+                                  float begin , float end );
+
+
+    VisualGroup* _generateGroup( const GIDUSet& gids , const std::string& name ,
+                                 unsigned int idx ) const;
+
+    void _updateGroupsModels( void );
+
+    void _generateGroupsIndices( void );
+
+    void _updateSelectionIndices( void );
+
+    void _generateSelectionIndices( void );
+
+    void _updateAttributesIndices( void );
+
+    void _generateAttributesIndices( void );
+
+    void _processFrameInputSelection( const simil::SpikesCRange& spikes_ ,
+                                      float begin , float end );
+
+    void _processFrameInputGroups( const simil::SpikesCRange& spikes_ ,
+                                   float begin , float end );
+
+    void _processFrameInputAttributes( const simil::SpikesCRange& spikes_ ,
+                                       float begin , float end );
+
+    void _loadPaletteColors( void );
+
+    void _clearSelectionView( void );
+
+    void _clearGroupsView( void );
+
+    void _clearAttribView( void );
+
+    void _clearGroups( void );
+
+    void _clearAttribs( bool clearCustom = true );
+
+    void _clearGroup( VisualGroup* group , bool clearState = true );
+
+    void _clearParticlesReference( void );
+
+    void _resetBoundingBox( void );
+
+    SourceMultiPosition* _getSource( unsigned int numParticles );
+
+#ifdef SIMIL_USE_BRION
+
+    tNeuronAttribs _loadNeuronTypes( const brion::BlueConfig& blueConfig );
+
+#endif
+
+    prefr::ParticleSystem* _particleSystem;
+
+    tGidPosMap _gidPositions;
+
+    TGIDSet _gids;
+
+    plab::Cluster< NeuronParticle > _clusterSelected;
+    plab::Cluster< NeuronParticle > _clusterUnselected;
+    plab::Cluster< NeuronParticle > _clusterHighlighted;
+
+    std::vector< VisualGroup* > _groups;
+    std::vector< VisualGroup* > _attributeGroups;
+    tNeuronAttributes _currentAttrib;
+
+    std::unordered_map< uint32_t , VisualGroup* > _neuronGroup;
+
+    std::unordered_map< unsigned int , SourceMultiPosition* > _gidSource;
+
+    tUintUMap _gidToParticle;
+    tUintUMap _particleToGID;
+
+    prefr::ColorOperationModel* _modelBase;
+    prefr::ColorOperationModel* _modelOff;
+    prefr::ColorOperationModel* _modelHighlighted;
+
+    tVisualMode _mode;
+
+    GIDUSet _selection;
+
+    float _decayValue;
+
+    bool _showInactive;
+
+    tBoundingBox _boundingBox;
+
+    std::vector< std::pair< QColor , QColor >> _paletteColors;
+
+    // Statistics
+    bool _groupByName;
+    bool _autoGroupByName;
+
+    tNeuronAttribs _gidTypes;
+
+    std::vector< std::string > _namesTypesMorpho;
+    std::vector< std::string > _namesTypesFunction;
+
+    std::vector< std::string > _namesTypesMorphoGrouped;
+    std::vector< std::string > _namesTypesFunctionGrouped;
+
+    std::vector< long unsigned int > _typesMorpho;
+    std::vector< long unsigned int > _typesFunction;
+
+    tUintUMap _typeToIdxMorpho;
+    tUintUMap _typeToIdxFunction;
+
+    tUintUMultimap _idxToTypeMorpho;
+    tUintUMultimap _idxToTypeFunction;
+
+    tUintUMap _statsMorpho;
+    tUintUMap _statsFunction;
+
+    std::unordered_map< std::string , unsigned int > _namesIdxMorpho;
+    std::unordered_map< std::string , unsigned int > _namesIdxFunction;
+  };
+}
+
+#endif /* __VISIMPL_VISUALGROUPMANAGER__ */
diff --git a/visimpl/OpenGLWidget.cpp b/visimpl/OpenGLWidget.cpp
index 66396fb84959bb85bc715b810c7ff89f55fc59cd..9367a6b173971b960135a82d7714fa60970a8eea 100644
--- a/visimpl/OpenGLWidget.cpp
+++ b/visimpl/OpenGLWidget.cpp
@@ -26,6 +26,7 @@
 #include "DomainManager.h"
 
 // Qt
+#include <QWidget>
 #include <QOpenGLContext>
 #include <QMouseEvent>
 #include <QColorDialog>
@@ -33,26 +34,18 @@
 #include <QGraphicsOpacityEffect>
 #include <QLabel>
 #include <QDir>
-#include <QMessageBox>
+#include <QOpenGLDebugLogger>
 
 // C++
-#include <sstream>
 #include <string>
 #include <iostream>
 #include <map>
-
 // GLM
 #include <glm/glm.hpp>
 
-// Prefr
-#include "prefr/PrefrShaders.h"
-#include "prefr/ColorSource.h"
-
 #ifdef SIMIL_USE_BRION
 
 #include <brain/brain.h>
-#include <brion/brion.h>
-#include <QOpenGLDebugLogger>
 
 #endif
 
@@ -62,6 +55,9 @@
 
 #endif
 
+#include "visimpl/particlelab/ParticleLabShaders.h"
+#include "GlewInitializer.h"
+
 constexpr float ZOOM_FACTOR = 1.3f;
 constexpr float TRANSLATION_FACTOR = 0.001f;
 constexpr float ROTATION_FACTOR = 0.01f;
@@ -144,24 +140,16 @@ void main()
     , _idleUpdate( true )
     , _paint( false )
     , _currentClearColor( 20 , 20 , 20 , 255 )
-    , _particleRadiusThreshold( 0.8 )
-    , _currentShader( T_SHADER_UNDEFINED )
-    , _shaderParticlesCurrent( nullptr )
-    , _shaderParticlesDefault( nullptr )
-    , _shaderParticlesSolid( nullptr )
-    , _shaderPicking( nullptr )
+    , _particleSystemInitialized( false )
     , _shaderClippingPlanes( nullptr )
-    , _particleSystem( nullptr )
-    , _pickRenderer( nullptr )
     , _player( nullptr )
-    , _clippingPlaneLeft( nullptr )
-    , _clippingPlaneRight( nullptr )
+    , _clippingPlaneLeft( std::make_shared< reto::ClippingPlane >( ))
+    , _clippingPlaneRight( std::make_shared< reto::ClippingPlane >( ))
     , _planeHeight( 1 )
     , _planeWidth( 1 )
     , _planeDistance( 20 )
     , _rotationPlanes( false )
     , _translationPlanes( false )
-    , _clipping( true )
     , _paintClippingPlanes( true )
     , _planesColor( 1.0 , 1.0 , 1.0 , 1.0 )
     , _deltaTime( 0.0f )
@@ -190,25 +178,16 @@ void main()
     , _alphaBlendingAccumulative( false )
     , _showSelection( false )
     , _flagNewData( false )
-    , _flagResetParticles( false )
     , _flagUpdateSelection( false )
-    , _flagUpdateGroups( false )
     , _flagUpdateAttributes( false )
-    , _flagPickingSingle( false )
-    , _flagPickingHighlighted( false )
-    , _flagChangeShader( false )
-    , _flagUpdateRender( false )
-    , _flagModeChange( false )
-    , _newMode( TMODE_UNDEFINED )
+    , _newMode( VisualMode::Selection )
     , _flagAttribChange( false )
     , _newAttrib( T_TYPE_UNDEFINED )
     , _currentAttrib( T_TYPE_MORPHO )
     , _showActiveEvents( true )
     , _subsetEvents( nullptr )
     , _deltaEvents( 0.125f )
-    , _domainManager( nullptr )
-    , _selectedPickingSingle( 0 )
-    , _oglFunctions{nullptr}
+    , _domainManager( )
     , _screenPlaneShader( nullptr )
     , _msaaFrameBuffer( 0 )
     , _msaaTextureColor( 0 )
@@ -275,7 +254,7 @@ void main()
           instance.connect( _zeqUri );
         }
 
-        _camera = new Camera( _zeqUri , instance.subscriber( ));
+        _camera = std::make_shared< Camera >( _zeqUri , instance.subscriber( ));
       }
       catch ( std::exception& e )
       {
@@ -293,14 +272,14 @@ void main()
       if ( failed )
       {
         std::cerr << "Unable to connect to ZeroEQ." << std::endl;
-        _camera = new Camera(reto::Camera::NO_ZEROEQ);
+        _camera = std::make_shared< Camera >( );
         _zeqUri.clear( );
       }
     }
 #else
-    _camera = new Camera( );
+      _camera = std::make_shared< Camera >(  );
 #endif
-    Q_ASSERT(_camera);
+    Q_ASSERT( _camera );
 
     setAutoFillBackground( true );
     setPalette( QPalette( QPalette::Window , Qt::black ));
@@ -308,29 +287,27 @@ void main()
 
   OpenGLWidget::~OpenGLWidget( void )
   {
-    if ( _camera )
-      delete _camera;
-
-    if ( _shaderParticlesDefault )
-      delete _shaderParticlesDefault;
-
-    if ( _shaderParticlesSolid )
-      delete _shaderParticlesSolid;
-
-    if ( _shaderPicking )
-      delete _shaderPicking;
-
-    if ( _particleSystem )
-      delete _particleSystem;
-
-    if ( _player )
-      delete _player;
+    delete _player;
   }
 
   void OpenGLWidget::initializeGL( void )
   {
     initializeOpenGLFunctions( );
 
+    auto* logger = new QOpenGLDebugLogger( this );
+    logger->initialize( );
+
+    connect(
+      logger , &QOpenGLDebugLogger::messageLogged ,
+      [ ]( const QOpenGLDebugMessage& message )
+      {
+        if ( message.severity( ) <= QOpenGLDebugMessage::MediumSeverity )
+          qDebug( ) << message;
+      }
+    );
+
+    logger->startLogging( );
+
     glEnable( GL_DEPTH_TEST );
     glClearColor( float( _currentClearColor.red( )) / 255.0f ,
                   float( _currentClearColor.green( )) / 255.0f ,
@@ -345,21 +322,32 @@ void main()
     _lastFrame = std::chrono::system_clock::now( );
 
     QOpenGLWidget::initializeGL( );
+    visimpl::GlewInitializer::init( );
+
+    const GLubyte* vendor = glGetString( GL_VENDOR ); // Returns the vendor
+    const GLubyte* renderer = glGetString(
+      GL_RENDERER ); // Returns a hint to the model
+    const GLubyte* version = glGetString( GL_VERSION );
+    const GLubyte* shadingVer = glGetString( GL_SHADING_LANGUAGE_VERSION );
+
+    _screenPlaneShader = new reto::ShaderProgram( );
+    _screenPlaneShader->loadVertexShaderFromText( vertexShaderCode );
+    _screenPlaneShader->loadFragmentShaderFromText( screenFragment );
+    _screenPlaneShader->create( );
+    _screenPlaneShader->link( );
+    _screenPlaneShader->autocatching( true );
+    _screenPlaneShader->use( );
+    _screenPlaneShader->sendUniformi( "screenTexture" , 0 );
 
-    const GLubyte* vendor = glGetString(GL_VENDOR); // Returns the vendor
-    const GLubyte* renderer = glGetString(GL_RENDERER); // Returns a hint to the model
-    const GLubyte* version = glGetString(GL_VERSION);
-    const GLubyte* shadingVer = glGetString(GL_SHADING_LANGUAGE_VERSION);
 
-    std::cout << "OpenGL Hardware: " << vendor << " (" << renderer << ")" << std::endl;
-    std::cout << "OpenGL Version: " << version << " (shading ver. " << shadingVer << ")" << std::endl;
+    std::cout << "OpenGL Hardware: " << vendor << " (" << renderer << ")"
+              << std::endl;
+    std::cout << "OpenGL Version: " << version << " (shading ver. "
+              << shadingVer << ")" << std::endl;
   }
 
   void OpenGLWidget::_initRenderToTexture( void )
   {
-    _oglFunctions = context( )->versionFunctions< QOpenGLFunctions_4_0_Core >( );
-    _oglFunctions->initializeOpenGLFunctions( );
-
     _screenPlaneShader = new reto::ShaderProgram( );
     _screenPlaneShader->loadVertexShaderFromText( vertexShaderCode );
     _screenPlaneShader->loadFragmentShaderFromText( screenFragment );
@@ -377,7 +365,7 @@ void main()
     glGenTextures( 1 , &_msaaTextureColor );
     glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , _msaaTextureColor );
 
-    _oglFunctions->glTexImage2DMultisample(
+    glTexImage2DMultisample(
       GL_TEXTURE_2D_MULTISAMPLE , SAMPLES , GL_RGB ,
       width( ) * FRAMEBUFFER_SCALE_FACTOR ,
       height( ) * FRAMEBUFFER_SCALE_FACTOR ,
@@ -392,7 +380,7 @@ void main()
 
     glGenRenderbuffers( 1 , &_msaaRBODepth );
     glBindRenderbuffer( GL_RENDERBUFFER , _msaaRBODepth );
-    _oglFunctions->glRenderbufferStorageMultisample(
+    glRenderbufferStorageMultisample(
       GL_RENDERBUFFER , SAMPLES , GL_DEPTH_COMPONENT32 ,
       width( ) * FRAMEBUFFER_SCALE_FACTOR ,
       height( ) * FRAMEBUFFER_SCALE_FACTOR );
@@ -442,11 +430,9 @@ void main()
 
   void OpenGLWidget::_configureSimulationFrame( void )
   {
-    if ( !_player || !_player->isPlaying( ) || !_particleSystem->run( ))
+    if ( !_player || !_player->isPlaying( ))
       return;
 
-    const float prevTime = _player->currentTime( );
-
     if ( _backtrace )
     {
       _backtraceSimulation( );
@@ -455,15 +441,12 @@ void main()
 
     _player->Frame( );
 
-    const float currentTime = _player->currentTime( );
-
-    _domainManager->processInput( _player->spikesNow( ) , prevTime ,
-                                  currentTime , false );
+    _domainManager.processInput( _player->spikesNow( ) , false );
   }
 
   void OpenGLWidget::_configurePreviousStep( void )
   {
-    if ( !_player || !_particleSystem->run( ))
+    if ( !_player )
       return;
 
     _sbsBeginTime = _sbsFirstStep ?
@@ -494,7 +477,7 @@ void main()
 
   void OpenGLWidget::_configureStepByStep( void )
   {
-    if ( !_player || !_player->isPlaying( ) || !_particleSystem->run( ))
+    if ( !_player || !_player->isPlaying( ))
       return;
 
     _sbsBeginTime = _sbsFirstStep ? _player->currentTime( ) : _sbsEndTime;
@@ -550,8 +533,7 @@ void main()
       {
         simil::SpikesCRange frameSpikes = std::make_pair( _sbsCurrentSpike ,
                                                           spikeIt );
-        _domainManager->processInput( frameSpikes , _sbsCurrentTime , nextTime ,
-                                      false );
+        _domainManager.processInput( frameSpikes , false );
       }
 
       _sbsCurrentTime = nextTime;
@@ -561,266 +543,86 @@ void main()
 
   void OpenGLWidget::_backtraceSimulation( void )
   {
-    if(!_player) return;
+    if ( !_player ) return;
 
     const float endTime = _player->currentTime( );
-    const float startTime = std::max( 0.0f , endTime - _domainManager->decay( ));
+    const float startTime = std::max( 0.0f ,
+                                      endTime - _domainManager.getDecay( ));
     if ( startTime < endTime )
     {
       const auto context = _player->spikesBetween( startTime , endTime );
 
+      _domainManager.setTime( endTime );
       if ( context.first != context.second )
-        _domainManager->processInput( context , startTime , endTime , true );
+        _domainManager.processInput( context , true );
     }
   }
 
   void OpenGLWidget::changeShader( int shaderIndex )
   {
-    if ( shaderIndex < 0 || shaderIndex >= static_cast<int>(T_SHADER_UNDEFINED))
-      return;
-
-    _currentShader = static_cast<tShaderParticlesType>(shaderIndex);
-    _flagChangeShader = true;
-  }
-
-  void OpenGLWidget::_setShaderParticles( void )
-  {
-    if ( _currentShader == T_SHADER_UNDEFINED )
-      return;
-
-    switch ( _currentShader )
-    {
-      case T_SHADER_DEFAULT:
-        _shaderParticlesCurrent = _shaderParticlesDefault;
-        break;
-      case T_SHADER_SOLID:
-        _shaderParticlesCurrent = _shaderParticlesSolid;
-        _shaderParticlesCurrent->use( );
-        _shaderParticlesCurrent->sendUniformf( "radiusThreshold" ,
-                                               _particleRadiusThreshold );
-        break;
-      default:
-        break;
-    }
-
-    auto render = _particleSystem->renderer( );
-    auto glRender = dynamic_cast<prefr::GLAbstractRenderer*>(render);
-
-    if ( glRender )
-    {
-      glRender->setRenderProgram( _shaderParticlesCurrent );
-    }
+    if ( shaderIndex == 0 )
+      _domainManager.applyDefaultShader( );
+    else if ( shaderIndex == 1 )
+      _domainManager.applySolidShader( );
   }
 
   void OpenGLWidget::createParticleSystem( )
   {
     makeCurrent( );
-    prefr::Config::init( );
-
-    // For debugging purposes only
-    bool success = false;
-    const auto shadersFile = std::getenv( "VISIMPL_SHADERS_FILE" );
-    if ( shadersFile )
-    {
-      QFile sFile{ QString::fromLocal8Bit( shadersFile ) };
-      if ( sFile.open( QIODevice::ReadOnly | QIODevice::Text ))
-      {
-        const auto contents = sFile.readAll( );
-        const auto shaders = contents.split( '@' );
-
-        if ( shaders.size( ) == 7 )
-        {
-          bool shadersSuccess[4]{ true , true , true , true };
-          auto prefrVertexShader = std::string( shaders.at( 0 ).data( ) ,
-                                                shaders.at( 0 ).size( ));
-
-          _shaderParticlesDefault = new prefr::RenderProgram( );
-          shadersSuccess[ 0 ] &= _shaderParticlesDefault->loadVertexShaderFromText(
-            std::string( shaders.at( 0 ).data( ) , shaders.at( 0 ).size( )));
-          shadersSuccess[ 0 ] &= _shaderParticlesDefault->loadFragmentShaderFromText(
-            std::string( shaders.at( 1 ).data( ) , shaders.at( 1 ).size( )));
-          shadersSuccess[ 0 ] &= _shaderParticlesDefault->compileAndLink( );
-          _shaderParticlesDefault->autocatching( );
-
-          if ( !shadersSuccess[ 0 ] )
-          {
-            std::cout << "shaders failed at _shaderParticlesDefault."
-                      << __FILE__ << ":" << __LINE__ << std::endl;
-          }
-
-          _shaderParticlesSolid = new prefr::RenderProgram( );
-          shadersSuccess[ 1 ] &= _shaderParticlesSolid->loadVertexShaderFromText(
-            std::string( shaders.at( 0 ).data( ) , shaders.at( 0 ).size( )));
-          shadersSuccess[ 1 ] &= _shaderParticlesSolid->loadFragmentShaderFromText(
-            std::string( shaders.at( 2 ).data( ) , shaders.at( 2 ).size( )));
-          shadersSuccess[ 1 ] &= _shaderParticlesSolid->compileAndLink( );
-          _shaderParticlesSolid->autocatching( );
-
-          if ( !shadersSuccess[ 1 ] )
-          {
-            std::cout << "shaders failed at _shaderParticlesSolid." << __FILE__
-                      << ":" << __LINE__ << std::endl;
-          }
-
-          _shaderPicking = new prefr::RenderProgram( );
-          shadersSuccess[ 2 ] &= _shaderPicking->loadVertexShaderFromText(
-            std::string( shaders.at( 3 ).data( ) , shaders.at( 3 ).size( )));
-          shadersSuccess[ 2 ] &= _shaderPicking->loadFragmentShaderFromText(
-            std::string( shaders.at( 4 ).data( ) , shaders.at( 4 ).size( )));
-          shadersSuccess[ 2 ] &= _shaderPicking->compileAndLink( );
-
-          if ( !shadersSuccess[ 2 ] )
-          {
-            std::cout << "shaders failed at _shaderPicking." << __FILE__ << ":"
-                      << __LINE__ << std::endl;
-          }
-
-          _shaderClippingPlanes = new prefr::RenderProgram( );
-          shadersSuccess[ 3 ] &= _shaderClippingPlanes->loadVertexShaderFromText(
-            std::string( shaders.at( 5 ).data( ) , shaders.at( 5 ).size( )));
-          shadersSuccess[ 3 ] &= _shaderClippingPlanes->loadFragmentShaderFromText(
-            std::string( shaders.at( 6 ).data( ) , shaders.at( 6 ).size( )));
-          shadersSuccess[ 3 ] &= _shaderClippingPlanes->compileAndLink( );
-          _shaderClippingPlanes->autocatching( );
-
-          if ( !shadersSuccess[ 3 ] )
-          {
-            std::cout << "shaders failed at _shaderClippingPlanes." << __FILE__
-                      << ":" << __LINE__ << std::endl;
-          }
-
-          if ( shadersSuccess[ 0 ] && shadersSuccess[ 1 ] &&
-               shadersSuccess[ 2 ] && shadersSuccess[ 3 ] )
-          {
-            success = true;
-            std::cout << "Loaded shaders from: "
-                      << sFile.fileName( ).toStdString( ) << std::endl;
-          }
-        }
-      }
-      else
-      {
-        std::cerr << "Unable to read " << sFile.fileName( ).toStdString( )
-                  << " reverting to default shaders.";
-      }
-    }
+    std::cout << "Loaded default shaders." << std::endl;
+    _updateData( );
 
-    if ( !success )
+    if ( !_particleSystemInitialized )
     {
-      // Default shaders.
-
-      // Initialize shader
-      _shaderParticlesDefault = new prefr::RenderProgram( );
-      _shaderParticlesDefault->loadVertexShaderFromText(
-        prefr::prefrVertexShader );
-      _shaderParticlesDefault->loadFragmentShaderFromText(
-        prefr::prefrFragmentShaderDefault );
-      _shaderParticlesDefault->compileAndLink( );
-      _shaderParticlesDefault->autocatching( );
-
-      _shaderParticlesSolid = new prefr::RenderProgram( );
-      _shaderParticlesSolid->loadVertexShaderFromText(
-        prefr::prefrVertexShader );
-      _shaderParticlesSolid->loadFragmentShaderFromText(
-        prefr::prefrFragmentShaderSolid );
-      _shaderParticlesSolid->compileAndLink( );
-      _shaderParticlesSolid->autocatching( );
-
-      _shaderPicking = new prefr::RenderProgram( );
-      _shaderPicking->loadVertexShaderFromText(
-        prefr::prefrVertexShaderPicking );
-      _shaderPicking->loadFragmentShaderFromText(
-        prefr::prefrFragmentShaderPicking );
-      _shaderPicking->compileAndLink( );
-
-      _shaderClippingPlanes = new prefr::RenderProgram( );
-      _shaderClippingPlanes->loadVertexShaderFromText( prefr::planeVertCode );
-      _shaderClippingPlanes->loadFragmentShaderFromText( prefr::planeFragCode );
+      _shaderClippingPlanes = new reto::ShaderProgram( );
+      _shaderClippingPlanes->loadVertexShaderFromText(
+        visimpl::SHADER_PLANE_VERTEX );
+      _shaderClippingPlanes->loadFragmentShaderFromText(
+        visimpl::SHADER_PLANE_FRAGMENT );
       _shaderClippingPlanes->compileAndLink( );
       _shaderClippingPlanes->autocatching( );
 
-      std::cout << "Loaded default shaders." << std::endl;
+      _domainManager.initRenderers(
+        _clippingPlaneLeft , _clippingPlaneRight , _camera );
     }
 
-    _currentShader = (_currentShader == T_SHADER_UNDEFINED) ? T_SHADER_DEFAULT : _currentShader;
-    _flagChangeShader = true;
-
-    unsigned int currentParticles = _player ? static_cast<unsigned int>( _player->gids( ).size( )) : 0u;
-    const unsigned int maxParticles =
-      std::max( 100000u , currentParticles);
-
-    _updateData( );
-    _particleSystem = new prefr::ParticleSystem( maxParticles , _camera );
-    _flagResetParticles = true;
-
-    if(!_player)
-    {
-      if(_domainManager) delete _domainManager;
-      _domainManager = nullptr;
-    }
-    else
+    if ( _player )
     {
-      _domainManager = new DomainManager( _particleSystem , _player->gids( ));
+      _domainManager.setSelection( _player->gids( ) , _gidPositions );
+
 #ifdef SIMIL_USE_BRION
-      _domainManager->init( _gidPositions , _player->data( )->blueConfig( ));
-#else
-      _domainManager->init( _gidPositions );
-#endif
-      _domainManager->initializeParticleSystem( _shaderParticlesDefault );
-      _domainManager->updateData( _player->gids( ) , _gidPositions );
-    }
 
-    _pickRenderer =
-      dynamic_cast< prefr::GLPickRenderer* >( _particleSystem->renderer( ));
+      _domainManager.initAttributeData( _player->gids( ) ,
+                                        _player
+                                        ? _player->data( )->blueConfig( )
+                                        : nullptr );
+      _domainManager.selectAttribute( _colorPalette.colors( ) , _gidPositions ,
+                                      tNeuronAttributes::T_TYPE_MORPHO );
+#endif
 
-    if ( _pickRenderer != nullptr )
-    {
-      _pickRenderer->glPickProgram( _shaderPicking );
-      _pickRenderer->setDefaultFBO( defaultFramebufferObject( ));
     }
 
-    if(_domainManager)
-      _domainManager->mode( TMODE_SELECTION );
+    _domainManager.setMode( VisualMode::Selection );
 
     updateCameraBoundingBox( true );
 
     _initClippingPlanes( );
+
+    _particleSystemInitialized = true;
   }
 
   void OpenGLWidget::_paintParticles( void )
   {
-    if ( !_particleSystem )
-      return;
-
-    _shaderParticlesCurrent->use( );
-
     glm::vec3 cameraPosition( _camera->position( )[ 0 ] ,
                               _camera->position( )[ 1 ] ,
                               _camera->position( )[ 2 ] );
 
-    if ( _player->isPlaying( ) || _lastCameraPosition != cameraPosition ||
-         _flagUpdateRender )
+    if ( _lastCameraPosition != cameraPosition )
     {
       _lastCameraPosition = cameraPosition;
-      _particleSystem->updateRender( );
-      _flagUpdateRender = false;
-    }
-
-    if ( _clipping )
-    {
-      _clippingPlaneLeft->activate( _shaderParticlesCurrent , 0 );
-      _clippingPlaneRight->activate( _shaderParticlesCurrent , 1 );
-    }
-
-    _particleSystem->render( );
-
-    if ( _clipping )
-    {
-      _clippingPlaneLeft->deactivate( 0 );
-      _clippingPlaneRight->deactivate( 1 );
     }
 
-    _shaderParticlesCurrent->unuse( );
+    _domainManager.draw( );
   }
 
   void OpenGLWidget::_paintPlanes( void )
@@ -837,35 +639,14 @@ void main()
     if ( _flagNewData )
       _updateNewData( );
 
-    if ( _flagChangeShader )
-      _setShaderParticles( );
-
-    if ( _flagModeChange )
-      _modeChange( );
-
     if ( _flagUpdateSelection )
       _updateSelection( );
 
-    if ( _flagUpdateGroups )
-      _updateGroupsVisibility( );
-
-    if ( _flagUpdateGroups && _domainManager && _domainManager->showGroups( ))
-      _updateGroups( );
-
     if ( _flagAttribChange )
       _attributeChange( );
 
     if ( _flagUpdateAttributes )
       _updateAttributes( );
-
-    if ( _flagResetParticles )
-    {
-      if ( _domainManager ) _domainManager->resetParticles( );
-      _flagResetParticles = false;
-    }
-
-    if ( _particleSystem )
-      _particleSystem->update( 0.0f );
   }
 
   void OpenGLWidget::paintGL( void )
@@ -900,105 +681,96 @@ void main()
     {
       _camera->anim( );
 
-      if ( _particleSystem )
+      if ( _player && _player->isPlaying( ))
       {
-        if ( _player && _player->isPlaying( ))
+        switch ( _playbackMode )
+        {
+          // Continuous mode (Default)
+          case TPlaybackMode::CONTINUOUS:
+            if ( _elapsedTimeSimAcc >= _simPeriodMicroseconds )
+            {
+              _configureSimulationFrame( );
+              _updateEventLabelsVisibility( );
+
+              _elapsedTimeSimAcc = 0.0f;
+            }
+            break;
+            // Step by step mode
+          case TPlaybackMode::STEP_BY_STEP:
+            if ( _sbsPrevStep )
+            {
+              _configurePreviousStep( );
+              _sbsPrevStep = false;
+            }
+            else if ( _sbsNextStep )
+            {
+              _configureStepByStep( );
+              _sbsNextStep = false;
+            }
+            break;
+          default:
+            break;
+        }
+
+        if ( _elapsedTimeRenderAcc >= _renderPeriodMicroseconds )
         {
+          double renderDelta = 0;
+
           switch ( _playbackMode )
           {
-            // Continuous mode (Default)
             case TPlaybackMode::CONTINUOUS:
-              if ( _elapsedTimeSimAcc >= _simPeriodMicroseconds )
-              {
-                _configureSimulationFrame( );
-                _updateEventLabelsVisibility( );
-
-                _elapsedTimeSimAcc = 0.0f;
-              }
+              renderDelta =
+                _elapsedTimeRenderAcc * _simTimePerSecond * 0.000001;
               break;
-              // Step by step mode
             case TPlaybackMode::STEP_BY_STEP:
-              if ( _sbsPrevStep )
-              {
-                _configurePreviousStep( );
-                _sbsPrevStep = false;
-              }
-              else if ( _sbsNextStep )
-              {
-                _configureStepByStep( );
-                _sbsNextStep = false;
-              }
+              _configureStepByStepFrame( _elapsedTimeRenderAcc * 0.000001 );
+              renderDelta = _sbsCurrentRenderDelta;
               break;
             default:
-              break;
+              renderDelta = 0;
           }
 
-          if ( _elapsedTimeRenderAcc >= _renderPeriodMicroseconds )
-          {
-            double renderDelta = 0;
+          if ( std::isnan( renderDelta )) renderDelta = 0;
 
-            switch ( _playbackMode )
-            {
-              case TPlaybackMode::CONTINUOUS:
-                renderDelta =
-                  _elapsedTimeRenderAcc * _simTimePerSecond * 0.000001;
-                break;
-              case TPlaybackMode::STEP_BY_STEP:
-                _configureStepByStepFrame( _elapsedTimeRenderAcc * 0.000001 );
-                renderDelta = _sbsCurrentRenderDelta;
-                break;
-              default:
-                renderDelta = 0;
-            }
+          _updateParticles( renderDelta );
+          _elapsedTimeRenderAcc = 0.0f;
+        } // elapsed > render period
 
-            if ( std::isnan( renderDelta )) renderDelta = 0;
-
-            _updateParticles( renderDelta );
-            _elapsedTimeRenderAcc = 0.0f;
-          } // elapsed > render period
-
-        } // if player && player->isPlaying
-
-
-        glBindFramebuffer( GL_FRAMEBUFFER , _msaaFrameBuffer );
-        glViewport( 0 , 0 , width( ) * FRAMEBUFFER_SCALE_FACTOR ,
-                    height( ) * FRAMEBUFFER_SCALE_FACTOR );
-        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-        glEnable( GL_DEPTH_TEST );
-
-        _paintPlanes( );
-        _paintParticles( );
-
-        glViewport( 0 , 0 , width( ) , height( ));
-
-        // Perform MSAA
-        glBindFramebuffer( GL_READ_FRAMEBUFFER , _msaaFrameBuffer );
-        glBindFramebuffer( GL_DRAW_FRAMEBUFFER , _midFrameBuffer );
-        int w = width( ) * FRAMEBUFFER_SCALE_FACTOR;
-        int h = height( ) * FRAMEBUFFER_SCALE_FACTOR;
-        _oglFunctions->glBlitFramebuffer(
-          0 , 0 ,
-          w , h ,
-          0 , 0 ,
-          w , h ,
-          GL_COLOR_BUFFER_BIT , GL_NEAREST );
-
-        // Perform super-sampling
-        glBindFramebuffer( GL_READ_FRAMEBUFFER , _midFrameBuffer );
-        glBindFramebuffer( GL_DRAW_FRAMEBUFFER , defaultFramebufferObject( ));
-        _oglFunctions->glBlitFramebuffer(
-          0 , 0 ,
-          w , h ,
-          0 , 0 ,
-          width( ) , height( ) ,
-          GL_COLOR_BUFFER_BIT , GL_LINEAR );
-
-        if ( _flagPickingSingle )
-        {
-          _pickSingle( );
-        }
-      } // if particleSystem
+      } // if player && player->isPlaying
 
+
+      glBindFramebuffer( GL_FRAMEBUFFER , _msaaFrameBuffer );
+      glViewport( 0 , 0 , width( ) * FRAMEBUFFER_SCALE_FACTOR ,
+                  height( ) * FRAMEBUFFER_SCALE_FACTOR );
+      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+      glEnable( GL_DEPTH_TEST );
+
+      _paintPlanes( );
+      _paintParticles( );
+
+      glViewport( 0 , 0 , width( ) , height( ));
+
+      // Perform MSAA
+      glBindFramebuffer( GL_READ_FRAMEBUFFER , _msaaFrameBuffer );
+      glBindFramebuffer( GL_DRAW_FRAMEBUFFER , _midFrameBuffer );
+      int w = width( ) * FRAMEBUFFER_SCALE_FACTOR;
+      int h = height( ) * FRAMEBUFFER_SCALE_FACTOR;
+      glBlitFramebuffer(
+        0 , 0 ,
+        w , h ,
+        0 , 0 ,
+        w , h ,
+        GL_COLOR_BUFFER_BIT , GL_NEAREST );
+
+      // Perform super-sampling
+      glBindFramebuffer( GL_READ_FRAMEBUFFER , _midFrameBuffer );
+      glBindFramebuffer( GL_DRAW_FRAMEBUFFER , defaultFramebufferObject( ));
+      glBlitFramebuffer(
+        0 , 0 ,
+        w , h ,
+        0 , 0 ,
+        width( ) , height( ) ,
+        GL_COLOR_BUFFER_BIT , GL_LINEAR );
     }
 
     if ( _player && _elapsedTimeSliderAcc > _sliderUpdatePeriodMicroseconds )
@@ -1011,7 +783,6 @@ void main()
 
       emit updateSlider( _player->GetRelativeTime( ));
 
-
       if ( _showCurrentTime )
       {
         _labelCurrentTime->setText(
@@ -1046,8 +817,9 @@ void main()
       _frameCount = 0;
     }
 
-    if ( _idleUpdate && _player )
-      update( );
+    update( );
+    //if ( _idleUpdate && _player )
+    //update( );
   }
 
   void
@@ -1067,11 +839,6 @@ void main()
     _flagUpdateSelection = true;
   }
 
-  void OpenGLWidget::setUpdateGroups( void )
-  {
-    _flagUpdateGroups = true;
-  }
-
   void OpenGLWidget::setUpdateAttributes( void )
   {
     _flagAttribChange = true;
@@ -1079,9 +846,8 @@ void main()
 
   void OpenGLWidget::selectAttrib( int newAttrib )
   {
-    if ( _domainManager &&
-         ( newAttrib < 0 || newAttrib >= static_cast<int>(T_TYPE_UNDEFINED) ||
-           _domainManager->mode( ) != TMODE_ATTRIBUTE ))
+    if (( newAttrib < 0 || newAttrib >= static_cast<int>(T_TYPE_UNDEFINED) ||
+          _domainManager.getMode( ) != VisualMode::Attribute ))
       return;
 
     _newAttrib = static_cast<tNeuronAttributes>(newAttrib);
@@ -1090,20 +856,16 @@ void main()
 
   void OpenGLWidget::_modeChange( void )
   {
-    if ( _domainManager )
-      _domainManager->mode( _newMode );
-
-    _flagModeChange = false;
-    _flagUpdateRender = true;
+    _domainManager.setMode( _newMode );
 
-    if ( _domainManager && ( _domainManager->mode( ) == TMODE_ATTRIBUTE ))
+    if ( _domainManager.getMode( ) == VisualMode::Attribute )
       emit attributeStatsComputed( );
   }
 
   void OpenGLWidget::_attributeChange( void )
   {
-    if ( _domainManager )
-      _domainManager->generateAttributesGroups( _newAttrib );
+    _domainManager.selectAttribute(
+      _colorPalette.colors( ) , _gidPositions , _newAttrib );
 
     _currentAttrib = _newAttrib;
 
@@ -1114,73 +876,17 @@ void main()
 
   void OpenGLWidget::_updateSelection( void )
   {
-    if(!_particleSystem || !_player) return;
-
-    _particleSystem->run(false);
+    if ( !_player ) return;
 
-    updateCameraBoundingBox();
-
-    _particleSystem->run(true);
-    _particleSystem->update(0.0f);
+    updateCameraBoundingBox( );
 
     _flagUpdateSelection = false;
-    _flagUpdateRender = true;
-  }
-
-  void OpenGLWidget::setGroupVisibility( unsigned int i , bool state )
-  {
-    _pendingGroupStateChanges.push( std::make_pair( i , state ));
-    _flagUpdateGroups = true;
-  }
-
-  void OpenGLWidget::_updateGroupsVisibility( void )
-  {
-    while ( !_pendingGroupStateChanges.empty( ))
-    {
-      auto state = _pendingGroupStateChanges.front( );
-      if ( _domainManager )
-        _domainManager->setVisualGroupState( state.first , state.second );
-
-      _pendingGroupStateChanges.pop( );
-
-      _flagUpdateRender = true;
-    }
-  }
-
-  void OpenGLWidget::_updateGroups( void )
-  {
-    if ( _particleSystem /*&& _pendingSelection*/ )
-    {
-      _particleSystem->run( false );
-
-      _domainManager->updateGroups( );
-
-      updateCameraBoundingBox( );
-
-      _particleSystem->run( true );
-      _particleSystem->update( 0.0f );
-
-      _flagUpdateGroups = false;
-      _flagUpdateRender = true;
-    }
   }
 
   void OpenGLWidget::_updateAttributes( void )
   {
-    if ( _particleSystem )
-    {
-      _particleSystem->run( false );
-
-      _domainManager->updateAttributes( );
-
-      updateCameraBoundingBox( );
-
-      _particleSystem->run( true );
-      _particleSystem->update( 0.0f );
-
-      _flagUpdateAttributes = false;
-      _flagUpdateRender = true;
-    }
+    updateCameraBoundingBox( );
+    _flagUpdateAttributes = false;
   }
 
   void OpenGLWidget::updateData( )
@@ -1190,10 +896,10 @@ void main()
 
   bool OpenGLWidget::_updateData( bool force )
   {
-    if(!_player)
+    if ( !_player )
     {
       _gidPositions.clear( );
-      _boundingBoxHome = tBoundingBox{ vec3{0,0,0}, vec3{0,0,0} };
+      _boundingBoxHome = tBoundingBox{ vec3{ 0 , 0 , 0 } , vec3{ 0 , 0 , 0 }};
       return false;
     }
 
@@ -1205,8 +911,8 @@ void main()
     _gidPositions.clear( );
     _gidPositions.reserve( positions.size( ));
 
-    vec3 bbmin;
-    vec3 bbmax;
+    vec3 bbmin = vec3( );
+    vec3 bbmax = vec3( );
     auto gidit = _player->gids( ).cbegin( );
     auto insertElement = [ & ]( const vmml::Vector3f& v )
     {
@@ -1215,27 +921,27 @@ void main()
                            v.z( ) * _scaleFactor.z );
 
       _gidPositions.insert( std::make_pair( *gidit , position ));
-      if(gidit == _player->gids().cbegin())
+      if ( gidit == _player->gids( ).cbegin( ))
       {
         bbmin = bbmax = position;
       }
       else
       {
-        auto x = std::min(bbmin.x, position.x);
-        auto y = std::min(bbmin.y, position.y);
-        auto z = std::min(bbmin.z, position.z);
-        bbmin = vec3{x,y,z};
-
-        x = std::max(bbmax.x, position.x);
-        y = std::max(bbmax.y, position.y);
-        z = std::max(bbmax.z, position.z);
-        bbmax = vec3{x,y,z};
+        auto x = std::min( bbmin.x , position.x );
+        auto y = std::min( bbmin.y , position.y );
+        auto z = std::min( bbmin.z , position.z );
+        bbmin = vec3{ x , y , z };
+
+        x = std::max( bbmax.x , position.x );
+        y = std::max( bbmax.y , position.y );
+        z = std::max( bbmax.z , position.z );
+        bbmax = vec3{ x , y , z };
       }
       ++gidit;
     };
     std::for_each( positions.cbegin( ) , positions.cend( ) , insertElement );
 
-    _boundingBoxHome = tBoundingBox{ bbmin, bbmax };
+    _boundingBoxHome = tBoundingBox{ bbmin , bbmax };
 
     return true;
   }
@@ -1243,27 +949,22 @@ void main()
   void OpenGLWidget::_updateNewData( void )
   {
     _flagNewData = false;
-
     if ( !_updateData( )) return;
-
-    _domainManager->updateData( _player->gids( ) , _gidPositions );
-    _focusOn( _domainManager->boundingBox( ));
-    _flagUpdateRender = true;
+    _domainManager.setSelection( _player->gids( ) , _gidPositions );
   }
 
   void OpenGLWidget::setMode( int mode )
   {
-    if ( mode < 0 || ( mode >= static_cast<int>(TMODE_UNDEFINED) ))
+    if ( mode < 0 || ( mode >= static_cast<int>(VisualMode::Undefined)))
       return;
 
-    _newMode = static_cast<tVisualMode>(mode);
-    _flagModeChange = true;
+    _newMode = static_cast<VisualMode>(mode);
+    _modeChange( );
   }
 
-  void OpenGLWidget::showInactive( bool state )
+  void OpenGLWidget::showInactive( bool /*state*/ )
   {
-    if ( _domainManager )
-      _domainManager->showInactive( state );
+    // TODO _domainManager.showInactive( state );
   }
 
   void OpenGLWidget::clearSelection( void )
@@ -1274,20 +975,20 @@ void main()
 
   void OpenGLWidget::home( void )
   {
-    if(_homePosition.isEmpty())
+    if ( _homePosition.isEmpty( ))
     {
       _focusOn( _boundingBoxHome );
-      _homePosition = cameraPosition().toString();
+      _homePosition = cameraPosition( ).toString( );
     }
 
-    setCameraPosition(_homePosition);
+    setCameraPosition( _homePosition );
   }
 
   void OpenGLWidget::updateCameraBoundingBox( bool setBoundingBox )
   {
-    if ( _gidPositions.empty( ) || !_domainManager) return;
+    if ( _gidPositions.empty( )) return;
 
-    const auto boundingBox = _domainManager->boundingBox( );
+    const auto boundingBox = _domainManager.getBoundingBox( );
 
     const glm::vec3 MAX{ std::numeric_limits< float >::max( ) ,
                          std::numeric_limits< float >::max( ) ,
@@ -1315,44 +1016,6 @@ void main()
     _camera->radius( radius );
   }
 
-  void OpenGLWidget::_pickSingle( void )
-  {
-    _shaderPicking->use( );
-    unsigned int shader = _shaderPicking->program( );
-    unsigned int particleRadius = glGetUniformLocation( shader ,
-                                                        "radiusThreshold" );
-
-    glUniform1f( particleRadius , _particleRadiusThreshold );
-
-    auto result =
-      _pickRenderer->pick( *_particleSystem ,
-                           _pickingPosition.x( ) ,
-                           _pickingPosition.y( ));
-
-    _flagPickingSingle = false;
-
-    if ( result == 0 ||
-         ( result - 1 == _selectedPickingSingle && _flagPickingHighlighted ))
-    {
-      _domainManager->clearHighlighting( );
-      _flagUpdateRender = true;
-      _flagPickingHighlighted = false;
-      return;
-    }
-
-    _flagPickingHighlighted = true;
-
-    _selectedPickingSingle = result - 1;
-
-    std::unordered_set< unsigned int > selected = { _selectedPickingSingle };
-
-    _domainManager->highlightElements( selected );
-
-    _flagUpdateRender = true;
-
-    emit pickedSingle( _selectedPickingSingle );
-  }
-
   void OpenGLWidget::showEventsActivityLabels( bool show )
   {
     auto updateWidget = [ show ]( visimpl::OpenGLWidget::EventLabel& container )
@@ -1378,11 +1041,9 @@ void main()
     if ( update && _player )
     {
       _updateData( true );
-      _domainManager->updateData( _player->gids( ) , _gidPositions );
-      _focusOn( _domainManager->boundingBox( ));
+      _domainManager.setSelection( _player->gids( ) , _gidPositions );
+      _focusOn( _domainManager.getBoundingBox( ));
     }
-
-    _flagUpdateRender = true;
   }
 
   vec3 OpenGLWidget::circuitScaleFactor( void ) const
@@ -1392,16 +1053,16 @@ void main()
 
   void OpenGLWidget::_updateParticles( float renderDelta )
   {
-    if ( _player && (_player->isPlaying( ) || _firstFrame ))
+    if ( _player && ( _player->isPlaying( ) || _firstFrame ))
     {
-      _particleSystem->update( renderDelta );
+      _domainManager.addTime( renderDelta, _player->endTime() );
       _firstFrame = false;
     }
   }
 
   void OpenGLWidget::_updateEventLabelsVisibility( void )
   {
-    if(!_player) return;
+    if ( !_player ) return;
 
     std::vector< bool > visibility = _activeEventsAt( _player->currentTime( ));
 
@@ -1422,7 +1083,7 @@ void main()
   {
     std::vector< bool > result( _eventLabels.size( ) , false );
 
-    if(_player)
+    if ( _player )
     {
       const float totalTime = _player->endTime( ) - _player->startTime( );
       const double perc = time / totalTime;
@@ -1445,23 +1106,23 @@ void main()
     _camera->windowSize( w , h );
     glViewport( 0 , 0 , w , h );
 
-    if ( _pickRenderer )
-    {
-      _pickRenderer->setWindowSize( w , h );
-    }
+    //if ( _pickRenderer )
+    //{
+    //  _pickRenderer->setWindowSize( w , h );
+    //}
 
-    if ( _oglFunctions != nullptr && _msaaTextureColor != 0 )
+    if ( _msaaTextureColor != 0 )
     {
       int rw = width( ) * FRAMEBUFFER_SCALE_FACTOR;
       int rh = height( ) * FRAMEBUFFER_SCALE_FACTOR;
       // Resize MSAA buffers
       glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , _msaaTextureColor );
-      _oglFunctions->glTexImage2DMultisample(
+      glTexImage2DMultisample(
         GL_TEXTURE_2D_MULTISAMPLE , SAMPLES , GL_RGB ,
         rw , rh , GL_TRUE );
 
       glBindRenderbuffer( GL_RENDERBUFFER , _msaaRBODepth );
-      _oglFunctions->glRenderbufferStorageMultisample(
+      glRenderbufferStorageMultisample(
         GL_RENDERBUFFER , SAMPLES , GL_DEPTH_COMPONENT32 ,
         rw , rh );
 
@@ -1484,9 +1145,6 @@ void main()
 
   void OpenGLWidget::_initClippingPlanes( void )
   {
-    _clippingPlaneLeft = new reto::ClippingPlane( );
-    _clippingPlaneRight = new reto::ClippingPlane( );
-
     _planePosLeft.resize( 4 , Eigen::Vector3f::Zero( ));
     _planePosRight.resize( 4 , Eigen::Vector3f::Zero( ));
 
@@ -1500,9 +1158,7 @@ void main()
 
   void OpenGLWidget::_genPlanesFromBoundingBox( void )
   {
-    if(!_domainManager) return;
-
-    auto currentBoundingBox = _domainManager->boundingBox( );
+    auto currentBoundingBox = _domainManager.getBoundingBox( );
 
     _planesCenter =
       glmToEigen( currentBoundingBox.first + currentBoundingBox.second ) * 0.5f;
@@ -1601,11 +1257,8 @@ void main()
   void OpenGLWidget::clippingPlanes( bool active )
   {
     _clipping = active;
-
-    if ( _clipping )
-    {
-      _updatePlanes( );
-    }
+    _domainManager.enableClipping( active );
+    if ( _clipping ) _updatePlanes( );
   }
 
   void OpenGLWidget::paintClippingPlanes( int paint_ )
@@ -1717,7 +1370,7 @@ void main()
     evec3 normal = -_planeNormalLeft;
     normal.normalize( );
 
-    auto positions = _domainManager->positions( );
+    auto positions = _gidPositions;
 
     result.reserve( positions.size( ));
 
@@ -1783,8 +1436,6 @@ void main()
       if ( _pickingPosition == event_->pos( ))
       {
         _pickingPosition.setY( height( ) - _pickingPosition.y( ));
-
-        _flagPickingSingle = true;
       }
 
       _translation = false;
@@ -1862,13 +1513,14 @@ void main()
     update( );
   }
 
-  void OpenGLWidget::setPlayer(simil::SpikesPlayer *p, const simil::TDataType type)
+  void OpenGLWidget::setPlayer( simil::SpikesPlayer* p ,
+                                const simil::TDataType type )
   {
     // Resets camera position
-    setCameraPosition(CameraPosition(INITIAL_CAMERA_POSITION));
-    _homePosition.clear();
+    setCameraPosition( CameraPosition( INITIAL_CAMERA_POSITION ));
+    _homePosition.clear( );
 
-    if(_player)
+    if ( _player )
     {
       // TODO: clear data?
     }
@@ -1926,7 +1578,7 @@ void main()
 
         _player->connectZeq( instance.subscriber( ) , instance.publisher( ));
         instance.startReceiveLoop( );
-        _zeqUri = std::string(); // clear to avoid re-connect.
+        _zeqUri = std::string( ); // clear to avoid re-connect.
       }
       catch ( std::exception& e )
       {
@@ -1941,8 +1593,8 @@ void main()
     }
 #endif
 
-    this->_paint = (_player != nullptr);
-    home(); // stores initial 'home' position.
+    this->_paint = ( _player != nullptr );
+    home( ); // stores initial 'home' position.
     update( );
   }
 
@@ -1960,9 +1612,10 @@ void main()
 
   void OpenGLWidget::changeClearColor( void )
   {
-    const auto color = QColorDialog::getColor( _currentClearColor , parentWidget( ) ,
-                       "Choose new background color" ,
-                       QColorDialog::DontUseNativeDialog );
+    const auto color = QColorDialog::getColor( _currentClearColor ,
+                                               parentWidget( ) ,
+                                               "Choose new background color" ,
+                                               QColorDialog::DontUseNativeDialog );
 
     if ( color.isValid( ))
     {
@@ -1974,12 +1627,12 @@ void main()
                     float( _currentClearColor.blue( )) / 255.0f ,
                     float( _currentClearColor.alpha( )) / 255.0f );
 
-      const QColor inverseColor{ 255 - _currentClearColor.red(),
-                                 255 - _currentClearColor.green(),
-                                 255 - _currentClearColor.blue(),
-                                 255};
+      const QColor inverseColor{ 255 - _currentClearColor.red( ) ,
+                                 255 - _currentClearColor.green( ) ,
+                                 255 - _currentClearColor.blue( ) ,
+                                 255 };
 
-      clippingPlanesColor(inverseColor);
+      clippingPlanesColor( inverseColor );
 
       update( );
     }
@@ -2052,7 +1705,7 @@ void main()
 
   float OpenGLWidget::currentTime( void )
   {
-    if(!_player) return 0.;
+    if ( !_player ) return 0.;
 
     switch ( _playbackMode )
     {
@@ -2065,14 +1718,14 @@ void main()
 
   DomainManager* OpenGLWidget::domainManager( void )
   {
-    return _domainManager;
+    return &_domainManager;
   }
 
   void OpenGLWidget::subsetEventsManager( simil::SubsetEventManager* manager )
   {
     _subsetEvents = manager;
 
-    if(manager) _createEventLabels( );
+    if ( manager ) _createEventLabels( );
 
     update( );
   }
@@ -2189,7 +1842,7 @@ void main()
     if ( _player )
     {
       _player->Stop( );
-      _flagResetParticles = true;
+      _domainManager.setTime( 0.0f );
       _firstFrame = true;
     }
   }
@@ -2206,14 +1859,11 @@ void main()
   {
     if ( _player )
     {
-      _particleSystem->run( false );
-      _flagResetParticles = true;
-
       _backtrace = true;
-
       std::cout << "Play at " << timePos << std::endl;
       _player->PlayAtTime( timePos );
-      _particleSystem->run( true );
+      _domainManager.setTime( timePos );
+
     }
   }
 
@@ -2226,7 +1876,6 @@ void main()
       if ( playing )
         _player->Play( );
 
-      _flagResetParticles = true;
       _firstFrame = true;
     }
   }
@@ -2258,18 +1907,14 @@ void main()
   void OpenGLWidget::SetAlphaBlendingAccumulative( bool accumulative )
   {
     _alphaBlendingAccumulative = accumulative;
-    if ( _particleSystem != nullptr )
-    {
-      _particleSystem->renderer( )->enableAccumulativeMode(
-        _alphaBlendingAccumulative );
-    }
+    _domainManager.enableAccumulativeMode( accumulative );
   }
 
   void
   OpenGLWidget::changeSimulationColorMapping( const TTransferFunction& colors )
   {
 
-    prefr::vectortvec4 gcolors;
+    visimpl::TColorVec gcolors;
 
     for ( const auto& c: colors )
     {
@@ -2277,80 +1922,43 @@ void main()
                         c.second.green( ) * invRGBInt ,
                         c.second.blue( ) * invRGBInt ,
                         c.second.alpha( ) * invRGBInt );
-
-      gcolors.Insert( c.first , gColor );
+      gcolors.emplace_back( c.first , gColor );
     }
 
-    if ( _domainManager )
-    {
-      _domainManager->modelSelectionBase( )->color = gcolors;
-
-      _flagUpdateRender = true;
-    }
+    _domainManager.getSelectionModel( )->setGradient( gcolors );
   }
 
   TTransferFunction OpenGLWidget::getSimulationColorMapping( void )
   {
     TTransferFunction result;
 
-    const auto model = _domainManager->modelSelectionBase( );
-    const auto colors = model->color.values;
+    const auto model = _domainManager.getSelectionModel( );
+    const auto colors = model->getGradient( );
 
-    auto timeValue = model->color.times.begin( );
-
-    auto insertColor = [ &timeValue , &result ]( const vec4 col )
+    for ( const auto& item: colors )
     {
+      auto col = item.second;
       const QColor color( col.r * 255 , col.g * 255 , col.b * 255 ,
                           col.a * 255 );
-      result.push_back( std::make_pair( *timeValue , color ));
-
-      ++timeValue;
-    };
-    std::for_each( colors.cbegin( ) , colors.cend( ) , insertColor );
+      result.push_back( std::make_pair( item.first , color ));
+    }
 
     return result;
   }
 
   void OpenGLWidget::changeSimulationSizeFunction( const TSizeFunction& sizes )
   {
-    utils::InterpolationSet< float > newSize;
-
-    auto insertSize = [ &newSize ]( const Event& e )
-    { newSize.Insert( e.first , e.second ); };
-    std::for_each( sizes.cbegin( ) , sizes.cend( ) , insertSize );
-
-    if ( _domainManager )
-    {
-      _domainManager->modelSelectionBase( )->size = newSize;
-
-      _flagUpdateRender = true;
-    }
+    _domainManager.getSelectionModel( )->setParticleSize( sizes );
   }
 
   TSizeFunction OpenGLWidget::getSimulationSizeFunction( void )
   {
-    TSizeFunction result;
-
-    if ( _domainManager )
-    {
-      const auto model = _domainManager->modelSelectionBase( );
-      const auto& sizes = model->size.times;
-
-      auto sizeValue = model->size.values.begin( );
-      auto insertSize = [ &result , &sizeValue ]( const float& f )
-      {
-        result.emplace_back( f , *sizeValue );
-        ++sizeValue;
-      };
-      std::for_each( sizes.cbegin( ) , sizes.cend( ) , insertSize );
-    }
-
-    return result;
+    return _domainManager.getSelectionModel( )->getParticleSize( );
   }
 
   void OpenGLWidget::simulationDeltaTime( float value )
   {
-    if(_player) _player->deltaTime( value );
+    if ( _player ) _player->deltaTime( value );
 
     _simDeltaTime = value;
 
@@ -2364,7 +1972,7 @@ void main()
 
   void OpenGLWidget::simulationStepsPerSecond( float value )
   {
-    if ( std::abs (value) < std::numeric_limits<float>::epsilon() ) return;
+    if ( std::abs( value ) < std::numeric_limits< float >::epsilon( )) return;
 
     _timeStepsPerSecond = value;
 
@@ -2391,43 +1999,44 @@ void main()
 
   void OpenGLWidget::changeSimulationDecayValue( float value )
   {
-    if ( _domainManager )
-      _domainManager->decay( value );
+    _domainManager.setDecay( value );
   }
 
   float OpenGLWidget::getSimulationDecayValue( void )
   {
-    return _domainManager->decay( );
+    return _domainManager.getDecay( );
   }
 
-  CameraPosition OpenGLWidget::cameraPosition() const
+  CameraPosition OpenGLWidget::cameraPosition( ) const
   {
     CameraPosition pos;
-    pos.position = _camera->position();
-    pos.radius   = _camera->radius();
-    pos.rotation = _camera->rotation();
+    pos.position = _camera->position( );
+    pos.radius = _camera->radius( );
+    pos.rotation = _camera->rotation( );
 
     return pos;
   }
 
-  void OpenGLWidget::setCameraPosition(const CameraPosition &pos)
+  void OpenGLWidget::setCameraPosition( const CameraPosition& pos )
   {
-    if(_camera)
+    if ( _camera )
     {
-      _camera->position(pos.position);
-      _camera->radius(pos.radius);
-      _camera->rotation(pos.rotation);
-      update();
+      _camera->position( pos.position );
+      _camera->radius( pos.radius );
+      _camera->rotation( pos.rotation );
+      update( );
     }
   }
 
-  void OpenGLWidget::resetParticles()
+  void OpenGLWidget::resetParticles( )
   {
-    _flagResetParticles = true;
-    _flagUpdateRender = true;
     _firstFrame = true;
+    update( );
+  }
 
-    update();
+  const tGidPosMap& OpenGLWidget::getGidPositions( ) const
+  {
+    return _gidPositions;
   }
 
 } // namespace visimpl
diff --git a/visimpl/OpenGLWidget.h b/visimpl/OpenGLWidget.h
index 04fa1ef398d4917cabbb3a7c6d502909d33f11f1..421376b872441e0021f464e87bd988258abdb1d5 100644
--- a/visimpl/OpenGLWidget.h
+++ b/visimpl/OpenGLWidget.h
@@ -23,14 +23,18 @@
 #ifndef __VISIMPL__OPENGLWIDGET__
 #define __VISIMPL__OPENGLWIDGET__
 
+#define PLAB_SKIP_GLEW_INCLUDE 1
+#define NEUROLOTS_SKIP_GLEW_INCLUDE 1
+
 #if defined(VISIMPL_USE_ZEROEQ) && defined(WIN32)
-  #include <winsock2.h>
+#include <winsock2.h>
 #endif
 
-// Qt
 #include <QOpenGLFunctions>
+#include <QOpenGLFunctions_3_3_Core>
+
+// Qt
 #include <QOpenGLWidget>
-#include <QOpenGLFunctions_4_0_Core>
 #include <QString>
 
 // C++
@@ -40,34 +44,23 @@
 #include <locale>
 #include <iostream>
 
-#define VISIMPL_SKIP_GLEW_INCLUDE 1
-
-#define PREFR_SKIP_GLEW_INCLUDE 1
-
-#define SIM_SLIDER_UPDATE_PERIOD 0.25f
-
-#include <prefr/prefr.h>
 #include <reto/reto.h>
-
-#include "types.h"
-
-#include "prefr/ColorSource.h"
-#include "prefr/ColorOperationModel.h"
-
-#include "render/Plane.h"
-
-#include "DomainManager.h"
-
 #include <sumrice/sumrice.h>
 #include <scoop/scoop.h>
+#include <plab/plab.h>
 
 #include <sstream>
 
+#include "types.h"
+#include "render/Plane.h"
+#include "DomainManager.h"
+
 class QLabel;
 
-struct streamDotSeparator: std::numpunct<char>
+struct streamDotSeparator : std::numpunct< char >
 {
-    char do_decimal_point() const { return '.'; }
+  char do_decimal_point( ) const
+  { return '.'; }
 };
 
 namespace visimpl
@@ -78,135 +71,154 @@ namespace visimpl
    */
   class CameraPosition
   {
-    public:
-      Eigen::Vector3f position; /** position point.  */
-      Eigen::Matrix3f rotation; /** rotation matrix. */
-      float radius;             /** aperture.        */
-
-      /** \brief CameraPosition class constructor.
-       *
-       */
-      CameraPosition()
-      : position{Eigen::Vector3f()}
-      , rotation{Eigen::Matrix3f::Zero()}
-      , radius{0}
-      {};
-
-      /** \brief CameraPosition class constructor.
-       * \param[in] data Camera position serialized data.
-       *
-       */
-      CameraPosition(const QString &data)
-      {
-        const auto separator = std::use_facet<std::numpunct<char>>(std::cout.getloc()).decimal_point();
-        const bool needSubst = (separator == ',');
-
-        auto parts = data.split(";");
-        Q_ASSERT(parts.size() == 3);
-        const auto posData = parts.first();
-        const auto rotData = parts.last();
-        auto radiusData = parts.at(1);
-
-        auto posParts = posData.split(",");
-        Q_ASSERT(posParts.size() == 3);
-        auto rotParts = rotData.split(",");
-        Q_ASSERT(rotParts.size() == 9);
-
-        if(needSubst)
-        {
-          for(auto &part: posParts) part.replace('.', ',');
-          for(auto &part: rotParts) part.replace('.', ',');
-          radiusData.replace('.', ',');
-        }
-
-        position = Eigen::Vector3f(posParts[0].toFloat(), posParts[1].toFloat(), posParts[2].toFloat());
-        radius = radiusData.toFloat();
-        rotation.block<1,3>(0,0) = Eigen::Vector3f{rotParts[0].toFloat(), rotParts[1].toFloat(), rotParts[2].toFloat()};
-        rotation.block<1,3>(1,0) = Eigen::Vector3f{rotParts[3].toFloat(), rotParts[4].toFloat(), rotParts[5].toFloat()};
-        rotation.block<1,3>(2,0) = Eigen::Vector3f{rotParts[6].toFloat(), rotParts[7].toFloat(), rotParts[8].toFloat()};
-      }
+  public:
+    Eigen::Vector3f position; /** position point.  */
+    Eigen::Matrix3f rotation; /** rotation matrix. */
+    float radius;             /** aperture.        */
 
-      /** \brief Returns the serialized camera position.
-       *
-       */
-      QString toString() const
+    /** \brief CameraPosition class constructor.
+     *
+     */
+    CameraPosition( )
+      : position{ Eigen::Vector3f( ) }
+      , rotation{ Eigen::Matrix3f::Zero( ) }
+      , radius{ 0 }
+    { };
+
+    /** \brief CameraPosition class constructor.
+     * \param[in] data Camera position serialized data.
+     *
+     */
+    CameraPosition( const QString& data )
+    {
+      const auto separator = std::use_facet< std::numpunct< char>>(
+        std::cout.getloc( )).decimal_point( );
+      const bool needSubst = ( separator == ',' );
+
+      auto parts = data.split( ";" );
+      Q_ASSERT( parts.size( ) == 3 );
+      const auto posData = parts.first( );
+      const auto rotData = parts.last( );
+      auto radiusData = parts.at( 1 );
+
+      auto posParts = posData.split( "," );
+      Q_ASSERT( posParts.size( ) == 3 );
+      auto rotParts = rotData.split( "," );
+      Q_ASSERT( rotParts.size( ) == 9 );
+
+      if ( needSubst )
       {
-        std::stringstream stream;
-        stream.imbue(std::locale(stream.getloc(), new streamDotSeparator()));
-        stream << position << ";" << radius << ";"
-               << rotation(0,0) << "," << rotation(0,1) << "," << rotation(0,2) << ","
-               << rotation(1,0) << "," << rotation(1,1) << "," << rotation(1,2) << ","
-               << rotation(2,0) << "," << rotation(2,1) << "," << rotation(2,2);
-
-        auto serialization = QString::fromStdString(stream.str());
-        serialization.replace('\n',',').remove(' ');
-
-        return serialization;
+        for ( auto& part: posParts ) part.replace( '.' , ',' );
+        for ( auto& part: rotParts ) part.replace( '.' , ',' );
+        radiusData.replace( '.' , ',' );
       }
+
+      position = Eigen::Vector3f( posParts[ 0 ].toFloat( ) ,
+                                  posParts[ 1 ].toFloat( ) ,
+                                  posParts[ 2 ].toFloat( ));
+      radius = radiusData.toFloat( );
+      rotation.block< 1 , 3 >( 0 , 0 ) = Eigen::Vector3f{
+        rotParts[ 0 ].toFloat( ) , rotParts[ 1 ].toFloat( ) ,
+        rotParts[ 2 ].toFloat( ) };
+      rotation.block< 1 , 3 >( 1 , 0 ) = Eigen::Vector3f{
+        rotParts[ 3 ].toFloat( ) , rotParts[ 4 ].toFloat( ) ,
+        rotParts[ 5 ].toFloat( ) };
+      rotation.block< 1 , 3 >( 2 , 0 ) = Eigen::Vector3f{
+        rotParts[ 6 ].toFloat( ) , rotParts[ 7 ].toFloat( ) ,
+        rotParts[ 8 ].toFloat( ) };
+    }
+
+    /** \brief Returns the serialized camera position.
+     *
+     */
+    QString toString( ) const
+    {
+      std::stringstream stream;
+      stream.imbue( std::locale( stream.getloc( ) , new streamDotSeparator( )));
+      stream << position << ";" << radius << ";"
+             << rotation( 0 , 0 ) << "," << rotation( 0 , 1 ) << ","
+             << rotation( 0 , 2 ) << ","
+             << rotation( 1 , 0 ) << "," << rotation( 1 , 1 ) << ","
+             << rotation( 1 , 2 ) << ","
+             << rotation( 2 , 0 ) << "," << rotation( 2 , 1 ) << ","
+             << rotation( 2 , 2 );
+
+      auto serialization = QString::fromStdString( stream.str( ));
+      serialization.replace( '\n' , ',' ).remove( ' ' );
+
+      return serialization;
+    }
   };
 
   typedef enum
   {
-    CONTINUOUS = 0,
-    STEP_BY_STEP,
+    CONTINUOUS = 0 ,
+    STEP_BY_STEP ,
     AB_REPEAT
   } TPlaybackMode;
 
   class OpenGLWidget
-  : public QOpenGLWidget
-  , public QOpenGLFunctions
+    : public QOpenGLWidget , public QOpenGLFunctions_3_3_Core
   {
-    Q_OBJECT;
+  Q_OBJECT;
 
   public:
     typedef enum
     {
-      tBlueConfig,
-      SWC,
+      tBlueConfig ,
+      SWC ,
       NsolScene
     } TDataFileType;
 
     typedef enum
     {
-      PROTOTYPE_OFF = 0,
+      PROTOTYPE_OFF = 0 ,
       PROTOTYPE_ON
     } TPrototypeEnum;
 
     struct EventLabel
     {
-      QWidget *upperWidget;
-      QLabel  *colorLabel;
-      QLabel  *label;
-
-      EventLabel():upperWidget{nullptr}, colorLabel{nullptr}, label{nullptr}{};
+      QWidget* upperWidget;
+      QLabel* colorLabel;
+      QLabel* label;
+
+      EventLabel( )
+        : upperWidget{ nullptr }
+        , colorLabel{ nullptr }
+        , label{ nullptr }
+      { };
     };
 
-    OpenGLWidget( QWidget* parent = nullptr,
-                  Qt::WindowFlags windowFlags = Qt::WindowFlags(),
+    OpenGLWidget( QWidget* parent = nullptr ,
+                  Qt::WindowFlags windowFlags = Qt::WindowFlags( ) ,
                   const std::string& zeqUri = "" );
-    virtual ~OpenGLWidget();
 
-    void createParticleSystem(  );
+    virtual ~OpenGLWidget( );
+
+    void createParticleSystem( );
 
     /** \brief Sets a new spikes player and initializes.
      * \param[in] p SpikesPlayer pointer.
      *
      */
-    void setPlayer(simil::SpikesPlayer *p, const simil::TDataType type);
+    void setPlayer( simil::SpikesPlayer* p , const simil::TDataType type );
+
+    const tGidPosMap& getGidPositions( ) const;
 
     void idleUpdate( bool idleUpdate_ = true );
 
     TPlaybackMode playbackMode( void );
+
     void playbackMode( TPlaybackMode mode );
 
     bool completedStep( void );
 
     simil::SimulationPlayer* player( );
+
     float currentTime( void );
 
-    void setGroupVisibility( unsigned int i, bool state );
+    void circuitScaleFactor( vec3 scale_ , bool update = true );
 
-    void circuitScaleFactor( vec3 scale_, bool update = true );
     vec3 circuitScaleFactor( void ) const;
 
     DomainManager* domainManager( void );
@@ -222,18 +234,18 @@ namespace visimpl
     /** \brief Returns the current camera position.
      *
      */
-    CameraPosition cameraPosition() const;
+    CameraPosition cameraPosition( ) const;
 
     /** \brief Moves the camera to the given position.
      * \param[in] pos CameraPosition reference.
      *
      */
-    void setCameraPosition(const CameraPosition &pos);
+    void setCameraPosition( const CameraPosition& pos );
 
     /** \brief Resets the view.
      *
      */
-    void resetParticles();
+    void resetParticles( );
 
   signals:
 
@@ -245,76 +257,108 @@ namespace visimpl
 
     void pickedSingle( unsigned int );
 
-    void planesColorChanged ( const QColor &);
+    void planesColorChanged( const QColor& );
 
   public slots:
 
     void updateData( void );
 
     void home( void );
+
     void updateCameraBoundingBox( bool setBoundingBox = false );
 
     void setMode( int mode );
+
     void showInactive( bool state );
 
     void changeShader( int i );
 
-    void setSelectedGIDs( const std::unordered_set< uint32_t >& gids  );
+    void setSelectedGIDs( const std::unordered_set< uint32_t >& gids );
+
     void clearSelection( void );
 
     void setUpdateSelection( void );
-    void setUpdateGroups( void );
+
     void setUpdateAttributes( void );
 
     void selectAttrib( int newAttrib );
 
     void showEventsActivityLabels( bool show );
+
     void showCurrentTimeLabel( bool show );
 
     void clippingPlanes( bool active );
+
     void paintClippingPlanes( int paint_ );
+
     void toggleClippingPlanes( void );
+
     void clippingPlanesReset( void );
+
     void clippingPlanesHeight( float height_ );
+
     float clippingPlanesHeight( void );
+
     void clippingPlanesWidth( float width_ );
+
     float clippingPlanesWidth( void );
+
     void clippingPlanesDistance( float distance_ );
+
     float clippingPlanesDistance( void );
+
     void clippingPlanesColor( const QColor& color_ );
+
     QColor clippingPlanesColor( void );
 
     void changeClearColor( void );
+
     void toggleUpdateOnIdle( void );
+
     void toggleShowFPS( void );
+
     void toggleWireframe( void );
 
     void Play( void );
+
     void Pause( void );
+
     void PlayPause( void );
+
     void Stop( void );
+
     void Repeat( bool repeat );
+
     void PlayAt( float timePos );
+
     void Restart( void );
+
     void PreviousStep( void );
+
     void NextStep( void );
 
     void changeSimulationColorMapping( const TTransferFunction& colors );
+
     TTransferFunction getSimulationColorMapping( void );
 
     void changeSimulationSizeFunction( const TSizeFunction& sizes );
+
     TSizeFunction getSimulationSizeFunction( void );
 
     void simulationDeltaTime( float value );
+
     float simulationDeltaTime( void );
 
     void simulationStepsPerSecond( float value );
+
     float simulationStepsPerSecond( void );
 
     void simulationStepByStepDuration( float value );
+
     float simulationStepByStepDuration( void );
 
     void changeSimulationDecayValue( float value );
+
     float getSimulationDecayValue( void );
 
     GIDVec getPlanesContainedElements( void ) const;
@@ -323,7 +367,9 @@ namespace visimpl
     void _resolveFlagsOperations( void );
 
     void _updateParticles( float renderDelta );
+
     void _paintParticles( void );
+
     void _paintPlanes( void );
 
     void _focusOn( const tBoundingBox& boundingBox );
@@ -331,62 +377,69 @@ namespace visimpl
     void _initClippingPlanes( void );
 
     void _genPlanesFromBoundingBox( void );
+
     void _genPlanesFromParameters( void );
-    void _updatePlanes( void );
-    void _rotatePlanes( float yaw, float pitch );
 
-    void _setShaderParticles( void );
+    void _updatePlanes( void );
 
-    void _pickSingle( void );
+    void _rotatePlanes( float yaw , float pitch );
 
     void _backtraceSimulation( void );
 
     void _initRenderToTexture( void );
 
     void _configureSimulationFrame( void );
+
     void _configureStepByStepFrame( double elapsedRenderTimeMilliseconds );
 
     void _configurePreviousStep( void );
+
     void _configureStepByStep( void );
 
     void _modeChange( void );
+
     void _attributeChange( void );
 
     void _updateSelection( void );
-    void _updateGroups( void );
-    void _updateGroupsVisibility( void );
+
     void _updateAttributes( void );
+
     void _updateNewData( void );
 
     bool _updateData( bool force = false );
 
     void _createEventLabels( void );
+
     void _updateEventLabelsVisibility( void );
 
     std::vector< bool > _activeEventsAt( float time );
 
     virtual void initializeGL( void );
+
     virtual void paintGL( void );
-    virtual void resizeGL( int w, int h );
+
+    virtual void resizeGL( int w , int h );
 
     virtual void mousePressEvent( QMouseEvent* event );
+
     virtual void mouseReleaseEvent( QMouseEvent* event );
+
     virtual void wheelEvent( QWheelEvent* event );
+
     virtual void mouseMoveEvent( QMouseEvent* event );
+
     virtual void keyPressEvent( QKeyEvent* event );
 
     /** \brief Connects the player to ZeroEQ signaling.
      *
      */
-    void connectPlayerZeroEQ();
+    void connectPlayerZeroEQ( );
 
     std::unordered_set< uint32_t > _selectedGIDs;
 
-    std::queue< std::pair< unsigned int, bool >> _pendingGroupStateChanges;
-
 #ifdef VISIMPL_USE_ZEROEQ
 
-  std::string _zeqUri;
+    std::string _zeqUri;
 
 #endif
 
@@ -397,7 +450,7 @@ namespace visimpl
 
     bool _wireframe;
 
-    Camera* _camera;
+    std::shared_ptr< Camera > _camera;
     glm::vec3 _lastCameraPosition;
 
     vec3 _scaleFactor;
@@ -411,7 +464,7 @@ namespace visimpl
 
     unsigned int _frameCount;
 
-    int _mouseX, _mouseY;
+    int _mouseX , _mouseY;
     bool _rotation;
     bool _translation;
 
@@ -424,20 +477,12 @@ namespace visimpl
     std::chrono::time_point< std::chrono::system_clock > _then;
     std::chrono::time_point< std::chrono::system_clock > _lastFrame;
 
-    tShaderParticlesType _currentShader;
-    prefr::RenderProgram* _shaderParticlesCurrent;
-    prefr::RenderProgram* _shaderParticlesDefault;
-    prefr::RenderProgram* _shaderParticlesSolid;
-    prefr::RenderProgram* _shaderPicking;
-    prefr::RenderProgram* _shaderClippingPlanes;
-
-    prefr::ParticleSystem* _particleSystem;
-    prefr::GLPickRenderer* _pickRenderer;
-
+    bool _particleSystemInitialized;
+    reto::ShaderProgram* _shaderClippingPlanes;
     simil::SpikesPlayer* _player;
 
-    reto::ClippingPlane* _clippingPlaneLeft;
-    reto::ClippingPlane* _clippingPlaneRight;
+    std::shared_ptr<reto::ClippingPlane> _clippingPlaneLeft;
+    std::shared_ptr<reto::ClippingPlane> _clippingPlaneRight;
     evec3 _planesCenter;
     evec3 _planeNormalLeft;
     evec3 _planeNormalRight;
@@ -496,17 +541,10 @@ namespace visimpl
     bool _showSelection;
 
     bool _flagNewData;
-    bool _flagResetParticles;
     bool _flagUpdateSelection;
-    bool _flagUpdateGroups;
     bool _flagUpdateAttributes;
-    bool _flagPickingSingle;
-    bool _flagPickingHighlighted;
-    bool _flagChangeShader;
-    bool _flagUpdateRender;
 
-    bool _flagModeChange;
-    tVisualMode _newMode;
+    VisualMode _newMode;
 
     bool _flagAttribChange;
     tNeuronAttributes _newAttrib;
@@ -519,19 +557,16 @@ namespace visimpl
     std::vector< std::vector< bool >> _eventsActivation;
     float _deltaEvents;
 
-    DomainManager* _domainManager;
+    DomainManager _domainManager;
     tBoundingBox _boundingBoxHome;
-    QString      _homePosition;
+    QString _homePosition;
 
     scoop::ColorPalette _colorPalette;
 
     QPoint _pickingPosition;
-    unsigned int _selectedPickingSingle;
 
     tGidPosMap _gidPositions; // particle positions * scale.
 
-    QOpenGLFunctions_4_0_Core* _oglFunctions;
-
     // Render to texture
     reto::ShaderProgram* _screenPlaneShader;
 
diff --git a/visimpl/SelectionManagerWidget.cpp b/visimpl/SelectionManagerWidget.cpp
index 821dec4d2d52edf10296b4440ddf26dfc43855f8..c0a52483ea29a519524a2c8214255f6efb6b2586 100644
--- a/visimpl/SelectionManagerWidget.cpp
+++ b/visimpl/SelectionManagerWidget.cpp
@@ -236,11 +236,21 @@ namespace visimpl
     if(all_.size() == _gidsAll.size()) return;
 
     _gidsAll.clear( );
+    _gidsSelected.clear();
+    _gidsAvailable.clear();
+    _gidIndex.clear();
+
     _gidsAll.insert( all_.begin( ), all_.end( ));
 
-    _fillLists( );
+    _modelAvailable->clear();
+    _modelSelected->clear();
 
+    _fillLists( );
     clearSelection();
+
+    _listViewAvailable->scrollToTop();
+    _listViewSelected->scrollToTop();
+
     setSelected( selected_ );
   }
 
diff --git a/visimpl/VisualGroup.cpp b/visimpl/VisualGroup.cpp
index b36793b98e7e765dfb0ec744b7df13dd55dae9a9..7092203fb2546517b8b528cbe8a7cc5f54950a89 100644
--- a/visimpl/VisualGroup.cpp
+++ b/visimpl/VisualGroup.cpp
@@ -29,40 +29,51 @@ namespace visimpl
 
   unsigned int VisualGroup::_counter = 0;
 
-  VisualGroup::VisualGroup( )
-  : _idx( _counter++ )
-  , _name( "" )
-  , _cluster( nullptr )
-  , _model( nullptr )
-  , _source( nullptr )
-  , _active( false )
-  , _cached( false )
-  , _dirty( false )
-  , _custom( false )
-  { }
-
-  VisualGroup::VisualGroup( const std::string& name )
-  : _idx( _counter++ )
-  , _name( name )
-  , _cluster( nullptr )
-  , _model( nullptr )
-  , _source( nullptr )
-  , _active( false )
-  , _cached( false )
-  , _dirty( false )
-  , _custom( false )
-  { }
+  VisualGroup::VisualGroup(
+    const std::shared_ptr< plab::ICamera >& camera ,
+    const std::shared_ptr< reto::ClippingPlane >& leftPlane ,
+    const std::shared_ptr< reto::ClippingPlane >& rightPlane ,
+    const std::shared_ptr< plab::Renderer >& renderer ,
+    bool enableClipping )
+    : _idx( _counter++ )
+    , _name( "" )
+    , _cluster( std::make_shared< plab::Cluster< NeuronParticle >>( ))
+    , _model( std::make_shared< StaticGradientModel >(
+      camera , leftPlane , rightPlane , TSizeFunction( ) , TColorVec( ) ,
+      true , enableClipping , 0.0f ))
+    , _active( true )
+  {
+    _cluster->setModel( _model );
+    _cluster->setRenderer( renderer );
+  }
+
+  VisualGroup::VisualGroup(
+    const std::string& name ,
+    const std::shared_ptr< plab::ICamera >& camera ,
+    const std::shared_ptr< reto::ClippingPlane >& leftPlane ,
+    const std::shared_ptr< reto::ClippingPlane >& rightPlane ,
+    const std::shared_ptr< plab::Renderer >& renderer ,
+    bool enableClipping )
+    : _idx( _counter++ )
+    , _name( name )
+    , _cluster( std::make_shared< plab::Cluster< NeuronParticle >>( ))
+    , _model( std::make_shared< StaticGradientModel >(
+      camera , leftPlane , rightPlane , TSizeFunction( ) ,
+      TColorVec( ) , true , enableClipping , 0.0f ))
+    , _active( true )
+  {
+    TColorVec vec;
+    vec.emplace_back( 0.0f , glm::vec4( 1.0f , 0.0f , 0.0f , 1.0f ));
+    vec.emplace_back( 1.0f , glm::vec4( 0.4f , 0.0f , 0.0f , 1.0f ));
+    _model->setGradient( vec );
+
+    _cluster->setModel( _model );
+    _cluster->setRenderer( renderer );
+  }
 
   VisualGroup::~VisualGroup( )
   {
-    if( _cluster )
-      delete _cluster;
-
-    if( _source )
-      delete _source;
-
-    if( _model )
-      delete _model;
+    _cluster->setModel( _model );
   }
 
   unsigned int VisualGroup::id( void )
@@ -80,12 +91,7 @@ namespace visimpl
     return _name;
   }
 
-  void VisualGroup::gids( const GIDUSet& gids_ )
-  {
-    _gids = gids_;
-  }
-
-  const GIDUSet& VisualGroup::gids( void ) const
+  const std::vector< uint32_t >& VisualGroup::getGids( ) const
   {
     return _gids;
   }
@@ -95,150 +101,74 @@ namespace visimpl
     return _active;
   }
 
-  void VisualGroup::active( bool state, bool updateSourceState )
+  void VisualGroup::active( bool state )
   {
     _active = state;
-
-    if( updateSourceState )
-      _source->active( state );
   }
 
-  void VisualGroup::cached( bool state )
+  void VisualGroup::setParticles( const std::vector< uint32_t >& gids ,
+                                  const std::vector< NeuronParticle >& particles )
   {
-    _cached = state;
+    _gids = gids;
+    _cluster->setParticles( particles );
   }
 
-  bool VisualGroup::cached( void ) const
+  void
+  VisualGroup::setRenderer( const std::shared_ptr< plab::Renderer >& renderer )
   {
-    return _cached;
+    _cluster->setRenderer( renderer );
   }
 
-  void VisualGroup::dirty( bool state )
+  const std::shared_ptr< plab::Cluster< NeuronParticle >>
+  VisualGroup::getCluster( ) const
   {
-    _dirty = state;
-  }
-
-  bool VisualGroup::dirty( void ) const
-  {
-    return _dirty;
-  }
-
-  void VisualGroup::custom( bool state )
-  {
-    _custom = state;
+    return _cluster;
   }
 
-  bool VisualGroup::custom( void ) const
+  const std::shared_ptr< StaticGradientModel > VisualGroup::getModel( ) const
   {
-    return _custom;
+    return _model;
   }
 
-  void VisualGroup::cluster( prefr::Cluster* cluster_ )
+  void VisualGroup::colorMapping( const TTransferFunction& colors )
   {
-    assert( cluster_ );
+    TColorVec gradient;
 
-    _cluster = cluster_;
-  }
+    auto insertColor = [ &gradient ]( const TTFColor& c )
+    {
+      glm::vec4 gColor( c.second.red( ) * invRGBInt ,
+                        c.second.green( ) * invRGBInt ,
+                        c.second.blue( ) * invRGBInt ,
+                        c.second.alpha( ) * invRGBInt );
 
-  prefr::Cluster* VisualGroup::cluster( void ) const
-  {
-    return _cluster;
-  }
+      gradient.emplace_back( c.first , gColor );
+    };
+    std::for_each( colors.cbegin( ) , colors.cend( ) , insertColor );
 
-  void VisualGroup::model( prefr::Model* model_ )
-  {
-    assert( model_ );
-
-    _model = model_;
+    _model->setGradient( gradient );
   }
 
-  prefr::Model* VisualGroup::model( void ) const
+  TTransferFunction VisualGroup::colorMapping( ) const
   {
-    return _model;
-  }
+    TTransferFunction result;
 
-  void VisualGroup::source( SourceMultiPosition* source_ )
-  {
-    assert( source_ );
+    for ( const auto& pair: _model->getGradient( ))
+    {
+      auto c = pair.second;
+      QColor color( c.r * 255 , c.g * 255 , c.b * 255 , c.a * 255 );
+      result.push_back( std::make_pair( pair.first , color ));
+    }
 
-    _source = source_;
+    return result;
   }
 
-  SourceMultiPosition* VisualGroup::source( void ) const
+  void VisualGroup::sizeFunction( const TSizeFunction& sizes )
   {
-    return _source;
+    _model->setParticleSize( sizes );
   }
 
-  QColor VisualGroup::color( void ) const
+  TSizeFunction VisualGroup::sizeFunction( ) const
   {
-    return _color;
+    return _model->getParticleSize( );
   }
-
-  void VisualGroup::colorMapping( const TTransferFunction& colors )
-   {
-     prefr::vectortvec4 gcolors;
-
-     auto insertColor = [&gcolors](const TTFColor &c)
-     {
-       glm::vec4 gColor( c.second.red( ) * invRGBInt,
-                         c.second.green( ) * invRGBInt,
-                         c.second.blue( ) * invRGBInt,
-                         c.second.alpha( ) * invRGBInt );
-
-       gcolors.Insert( c.first, gColor );
-     };
-     std::for_each(colors.cbegin(), colors.cend(), insertColor);
-
-     _color = colors[ 0 ].second;
-     _model->color = gcolors;
-   }
-
-  TTransferFunction VisualGroup::colorMapping( void ) const
-   {
-     TTransferFunction result;
-
-     auto timeValue = _model->color.times.begin( );
-     const auto values = _model->color.values;
-
-     auto mapColor = [&timeValue, &result](const vec4 &c)
-     {
-       QColor color( c.r * 255, c.g * 255, c.b * 255, c.a * 255 );
-       result.push_back( std::make_pair( *timeValue, color ));
-
-       ++timeValue;
-     };
-     std::for_each(values.cbegin(), values.cend(), mapColor);
-
-     return result;
-   }
-
-   void VisualGroup::sizeFunction( const TSizeFunction& sizes )
-   {
-     utils::InterpolationSet< float > newSize;
-
-     auto insertSize = [&newSize](const Event &e)
-     {
-       newSize.Insert( e.first, e.second );
-     };
-     std::for_each(sizes.cbegin(), sizes.cend(), insertSize);
-
-     _model->size = newSize;
-   }
-
-   TSizeFunction VisualGroup::sizeFunction( void ) const
-   {
-     TSizeFunction result;
-
-     auto sizeValue = _model->size.values.begin( );
-     const auto times = _model->size.times;
-
-     auto insertTime = [&sizeValue, &result](const float f)
-     {
-       result.push_back( std::make_pair( f, *sizeValue ));
-       ++sizeValue;
-     };
-     std::for_each(times.cbegin(), times.cend(), insertTime);
-
-     return result;
-   }
 }
diff --git a/visimpl/VisualGroup.h b/visimpl/VisualGroup.h
index 3ec5eba40493df96044c3e415adf3facff9480c9..8a94233ecb09755cd034de9036e7ff1acb726085 100644
--- a/visimpl/VisualGroup.h
+++ b/visimpl/VisualGroup.h
@@ -26,59 +26,66 @@
 // Sumrice
 #include <sumrice/sumrice.h>
 
-// Prefr
-#include <prefr/prefr.h>
+// Plab
+#include <plab/core/Cluster.h>
+#include <plab/reto/CameraModel.h>
 
 // Visimpl
-#include "prefr/SourceMultiPosition.h"
+#include "visimpl/particlelab/NeuronParticle.h"
+#include "visimpl/particlelab/StaticGradientModel.h"
 
 namespace visimpl
 {
   class VisualGroup
   {
-    friend class DomainManager;
+    friend class OldDomainManager;
 
   public:
-    VisualGroup( );
-    VisualGroup( const std::string& name );
+    VisualGroup(
+      const std::shared_ptr< plab::ICamera >& camera ,
+      const std::shared_ptr< reto::ClippingPlane >& leftPlane ,
+      const std::shared_ptr< reto::ClippingPlane >& rightPlane ,
+      const std::shared_ptr< plab::Renderer >& renderer ,
+      bool enableClipping );
+
+    VisualGroup(
+      const std::string& name ,
+      const std::shared_ptr< plab::ICamera >& camera ,
+      const std::shared_ptr< reto::ClippingPlane >& leftPlane ,
+      const std::shared_ptr< reto::ClippingPlane >& rightPlane ,
+      const std::shared_ptr< plab::Renderer >& renderer ,
+      bool enableClipping );
+
     ~VisualGroup( );
 
-    unsigned int id( void );
+    unsigned int id( );
 
     void name( const std::string& name_ );
-    const std::string& name( void ) const;
 
-    void gids( const GIDUSet& gids_ );
-    const GIDUSet& gids( void ) const;
+    const std::string& name( ) const;
 
-    QColor color( void ) const;
+    const std::vector< uint32_t >& getGids( ) const;
 
     void colorMapping( const TTransferFunction& colors );
-    TTransferFunction colorMapping( void ) const;
+
+    TTransferFunction colorMapping( ) const;
 
     void sizeFunction( const TSizeFunction& sizes );
-    TSizeFunction sizeFunction( void ) const;
 
-    void cluster( prefr::Cluster* cluster_ );
-    prefr::Cluster* cluster( void ) const;
+    TSizeFunction sizeFunction( ) const;
 
-    void model( prefr::Model* model_ );
-    prefr::Model* model( void ) const;
+    const std::shared_ptr< plab::Cluster< NeuronParticle >> getCluster( ) const;
 
-    void source( SourceMultiPosition* source_ );
-    SourceMultiPosition* source( void ) const;
+    const std::shared_ptr< StaticGradientModel > getModel( ) const;
 
-    void active( bool state, bool updateSourceState = false );
-    bool active( void ) const;
+    void active( bool state );
 
-    void cached( bool state );
-    bool cached( void ) const;
+    bool active( ) const;
 
-    void dirty( bool state );
-    bool dirty( void ) const;
+    void setParticles( const std::vector< uint32_t >& gids ,
+                       const std::vector< NeuronParticle >& particles );
 
-    void custom( bool state );
-    bool custom( void ) const;
+    void setRenderer( const std::shared_ptr< plab::Renderer >& renderer );
 
   protected:
     unsigned int _idx;
@@ -86,19 +93,12 @@ namespace visimpl
 
     std::string _name;
 
-    GIDUSet _gids;
+    std::shared_ptr< plab::Cluster< NeuronParticle >> _cluster;
+    std::shared_ptr< StaticGradientModel > _model;
 
-    prefr::Cluster* _cluster;
-    prefr::Model* _model;
-    SourceMultiPosition* _source;
-
-    QColor _color;
+    std::vector< uint32_t > _gids;
 
     bool _active;
-    bool _cached;
-    bool _dirty;
-
-    bool _custom;
   };
 }
 
diff --git a/visimpl/particlelab/NeuronParticle.cpp b/visimpl/particlelab/NeuronParticle.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8c7d0fd8b06ff1b8044681df6e0d810c25fdc36e
--- /dev/null
+++ b/visimpl/particlelab/NeuronParticle.cpp
@@ -0,0 +1,27 @@
+//
+// Created by gaeqs on 21/06/22.
+//
+
+#include <GL/glew.h>
+
+#include "NeuronParticle.h"
+
+namespace visimpl
+{
+
+  void NeuronParticle::enableVAOAttributes( )
+  {
+    glEnableVertexAttribArray( 1 );
+    glVertexAttribPointer( 1 , 3 , GL_FLOAT , GL_FALSE ,
+                           sizeof( NeuronParticle ) ,
+                           ( void* ) 0 );
+    glVertexAttribDivisor( 1 , 1 );
+
+    glEnableVertexAttribArray( 2 );
+    glVertexAttribPointer( 2 , 1 , GL_FLOAT , GL_FALSE ,
+                           sizeof( NeuronParticle ) ,
+                           ( void* ) ( sizeof( float ) * 3 ));
+    glVertexAttribDivisor( 2 , 1 );
+
+  }
+}
\ No newline at end of file
diff --git a/visimpl/particlelab/NeuronParticle.h b/visimpl/particlelab/NeuronParticle.h
new file mode 100644
index 0000000000000000000000000000000000000000..fe31f84489440936533d69a3c41da70f4e792981
--- /dev/null
+++ b/visimpl/particlelab/NeuronParticle.h
@@ -0,0 +1,27 @@
+//
+// Created by gaeqs on 21/06/22.
+//
+
+#ifndef VISIMPL_NEURONPARTICLE_H
+#define VISIMPL_NEURONPARTICLE_H
+
+#include <limits>
+
+#include <glm/vec3.hpp>
+
+namespace visimpl
+{
+
+  struct NeuronParticle
+  {
+    glm::vec3 position;
+    float timestamp = -std::numeric_limits<float>::infinity();
+
+    static void enableVAOAttributes( );
+
+  };
+
+}
+
+
+#endif //VISIMPL_NEURONPARTICLE_H
diff --git a/visimpl/prefr/PrefrShaders.h b/visimpl/particlelab/ParticleLabShaders.h
similarity index 57%
rename from visimpl/prefr/PrefrShaders.h
rename to visimpl/particlelab/ParticleLabShaders.h
index 8eb267c895cbf6a9f1bf3ec1ac37311c627d92d2..896cc5756279e73a34d07a88e69b0fdc8eba4abe 100644
--- a/visimpl/prefr/PrefrShaders.h
+++ b/visimpl/particlelab/ParticleLabShaders.h
@@ -23,48 +23,101 @@
 #ifndef PREFRSHADERS_H_
 #define PREFRSHADERS_H_
 
-namespace prefr
+#include <string>
+
+namespace visimpl
 {
 
-const static std::string prefrVertexShader = R"(
-#version 400
+const static std::string PARTICLE_VERTEX_SHADER = R"(#version 400
 //#extension GL_ARB_separate_shader_objects: enable
 
-uniform mat4 modelViewProjM;
+uniform mat4 viewProjectionMatrix;
 uniform vec3 cameraUp;
 uniform vec3 cameraRight;
 
+uniform float time;
+
+uniform int gradientSize;
+uniform float gradientTimes[256];
+uniform vec4 gradientColors[256];
+
+uniform int sizeSize;
+uniform float sizeTimes[16];
+uniform float sizeValues[16];
+
 // Clipping planes
-uniform vec4 plane[ 2 ];
-out float gl_ClipDistance[ 2 ];
+uniform vec4 plane[2];
+out float gl_ClipDistance[2];
 
 layout(location = 0) in vec3 vertexPosition;
-layout(location = 1) in float particleSize;
-layout(location = 2) in vec3 particlePosition;
-layout(location = 3) in vec4 particleColor;
+layout(location = 1) in vec3 particlePosition;
+layout(location = 2) in float timestamp;
 
 out vec4 color;
 out vec2 uvCoord;
 
+float sizeGradient (float t) {
+    if (sizeSize == 0) return 8.0f;
+    int first = sizeSize - 1;
+    for (int i = 0; i < sizeSize; i++) {
+        if (sizeTimes[i] > t) {
+            first = i - 1;
+            break;
+        }
+    }
+
+    // Particles have the last value before they reach the first value.
+    if (first == -1 || first == sizeSize - 1)
+    return sizeValues[sizeSize - 1];
+
+    float start = sizeTimes[first];
+    float end = sizeTimes[first + 1];
+    float normalizedT = (t - start) / (end - start);
+
+    return mix(sizeValues[first], sizeValues[first + 1], normalizedT);
+}
+
+vec4 gradient (float t) {
+    if (gradientSize == 0) return vec4(1.0f, 0.0f, 1.0f, 1.0f);
+    int first = gradientSize - 1;
+    for (int i = 0; i < gradientSize; i++) {
+        if (gradientTimes[i] > t) {
+            first = i - 1;
+            break;
+        }
+    }
+
+    // Particles have the last value before they reach the first value.
+    if (first == -1 || first == gradientSize - 1)
+      return gradientColors[gradientSize - 1];
+
+    float start = gradientTimes[first];
+    float end = gradientTimes[first + 1];
+    float normalizedT = (t - start) / (end - start);
+
+    return mix(gradientColors[first], gradientColors[first + 1], normalizedT);
+}
+
 void main()
 {
-  vec4 position =  vec4(
-        (vertexPosition.x * particleSize * cameraRight)
-        + (vertexPosition.y * particleSize * cameraUp)
-        + particlePosition, 1.0);
+    float particleSize = sizeGradient(time - timestamp);
+    vec4 position =  vec4(
+    (vertexPosition.x * particleSize * cameraRight)
+    + (vertexPosition.y * particleSize * cameraUp)
+    + particlePosition, 1.0);
 
-  gl_ClipDistance[ 0 ] = dot( position, plane[ 0 ]);
-  gl_ClipDistance[ 1 ] = dot( position, plane[ 1 ]);
+    gl_ClipDistance[0] = dot(position, plane[0]);
+    gl_ClipDistance[1] = dot(position, plane[1]);
 
-  gl_Position = modelViewProjM * position;
+    gl_Position = viewProjectionMatrix * position;
 
-  color = particleColor;
-  uvCoord = vertexPosition.rg + vec2(0.5, 0.5);
+    color = gradient(time - timestamp);
+    uvCoord = vertexPosition.rg + vec2(0.5, 0.5);
 }
 
 )";
 
-const static std::string prefrFragmentShaderDefault = R"(
+const static std::string PARTICLE_DEFAULT_FRAGMENT_SHADER = R"(
 #version 400
 in vec4 color; 
 in vec2 uvCoord;
@@ -80,9 +133,8 @@ void main()
 
 )";
 
-const static std::string prefrFragmentShaderSolid = R"(#version 400
-uniform float radiusThreshold;
-in vec4 color; 
+const static std::string PARTICLE_SOLID_FRAGMENT_SHADER = R"(#version 400
+in vec4 color;
 in vec2 uvCoord;
 out vec4 outputColor;
 void main()
@@ -91,13 +143,13 @@ void main()
   float l = sqrt(dot(p,p));
   l = clamp(l, 0.0, 1.0);
   
-  if( l > radiusThreshold )
+  if( l > 0.8 )
     discard;
 
   outputColor = vec4(color.rgb, 1.0f);
 })";
 
-const static std::string prefrVertexShaderPicking = R"(#version 400
+const static std::string PICK_VERTEX_SHADER = R"(#version 400
 #extension GL_ARB_separate_shader_objects: enable
 
 uniform mat4 modelViewProjM;
@@ -137,7 +189,7 @@ void main()
   id = gl_InstanceID;
 })";
 
-const static std::string prefrFragmentShaderPicking = R"(#version 400
+const static std::string PICK_FRAGMENT_SHADER = R"(#version 400
 
 uniform float radiusThreshold;
 
@@ -170,7 +222,7 @@ void main( )
   outputColor = vec4(cc, 1.0);
 })";
 
-const static std::string planeVertCode = R"(
+const static std::string SHADER_PLANE_VERTEX = R"(
 #version 400
 
 in vec3 inPos;
@@ -191,7 +243,7 @@ void main( )
 )";
 
 
-const static std::string planeFragCode = R"(
+const static std::string SHADER_PLANE_FRAGMENT = R"(
 #version 400
 
 in vec4 outColor;
diff --git a/visimpl/particlelab/StaticGradientModel.cpp b/visimpl/particlelab/StaticGradientModel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..32ea56a19d0dca5fab07d4bba0decc3b9b5662f4
--- /dev/null
+++ b/visimpl/particlelab/StaticGradientModel.cpp
@@ -0,0 +1,197 @@
+//
+// Created by gaeqs on 9/06/22.
+//
+
+#include <GL/glew.h>
+
+// ParticleLab
+#include <plab/plab.h>
+
+#include "StaticGradientModel.h"
+
+#include <QDebug>
+#include <cmath>
+
+namespace visimpl
+{
+
+  StaticGradientModel::StaticGradientModel(
+    const std::shared_ptr< plab::ICamera >& camera ,
+    const std::shared_ptr< reto::ClippingPlane >& leftPlane ,
+    const std::shared_ptr< reto::ClippingPlane >& rightPlane ,
+    const TSizeFunction& particleSize ,
+    const TColorVec& gradient ,
+    bool particleVisibility ,
+    bool clippingEnabled ,
+    float time )
+    : plab::CameraModel( camera )
+    , _leftPlane( leftPlane )
+    , _rightPlane( rightPlane )
+    , _particleSize( particleSize )
+    , _gradient( gradient )
+    , _particleVisibility( particleVisibility )
+    , _clippingEnabled( clippingEnabled )
+    , _time( time )
+  {
+
+  }
+
+  const std::shared_ptr< reto::ClippingPlane >&
+  StaticGradientModel::getLeftPlane( ) const
+  {
+    return _leftPlane;
+  }
+
+  void StaticGradientModel::setLeftPlane(
+    const std::shared_ptr< reto::ClippingPlane >& leftPlane )
+  {
+    _leftPlane = leftPlane;
+  }
+
+  const std::shared_ptr< reto::ClippingPlane >&
+  StaticGradientModel::getRightPlane( ) const
+  {
+    return _rightPlane;
+  }
+
+  void StaticGradientModel::setRightPlane(
+    const std::shared_ptr< reto::ClippingPlane >& rightPlane )
+  {
+    _rightPlane = rightPlane;
+  }
+
+  TSizeFunction StaticGradientModel::getParticleSize( ) const
+  {
+    return _particleSize;
+  }
+
+  void StaticGradientModel::setParticleSize( const TSizeFunction& particleSize )
+  {
+    _particleSize = particleSize;
+  }
+
+  const TColorVec& StaticGradientModel::getGradient( ) const
+  {
+    return _gradient;
+  }
+
+  void StaticGradientModel::setGradient( const TColorVec& gradient )
+  {
+    _gradient = gradient;
+  }
+
+  bool StaticGradientModel::isParticleVisibility( ) const
+  {
+    return _particleVisibility;
+  }
+
+  void StaticGradientModel::setParticleVisibility( bool particleVisibility )
+  {
+    _particleVisibility = particleVisibility;
+  }
+
+  bool StaticGradientModel::isClippingEnabled( ) const
+  {
+    return _clippingEnabled;
+  }
+
+  void StaticGradientModel::enableClipping( bool enabled )
+  {
+    _clippingEnabled = enabled;
+  }
+
+  float StaticGradientModel::getTime( ) const
+  {
+    return _time;
+  }
+
+  void StaticGradientModel::setTime( float time )
+  {
+    _time = time;
+  }
+
+  void StaticGradientModel::addTime( float time , float endTime )
+  {
+    _time = std::fmod( _time + time , endTime );
+  }
+
+  void
+  StaticGradientModel::uploadDrawUniforms( plab::UniformCache& cache ) const
+  {
+    constexpr int MAX_COLORS = 256;
+    constexpr int MAX_SIZES = 16;
+
+    CameraModel::uploadDrawUniforms( cache );
+
+    glUniform1f( cache.getLocation( "time" ) , _time );
+
+
+    {
+      int maxSize = std::min( MAX_SIZES ,
+                              static_cast<int>(_particleSize.size( )));
+      glUniform1i( cache.getLocation( "sizeSize" ) , maxSize );
+
+      float timeStamps[MAX_SIZES];
+      float values[MAX_SIZES];
+
+      for ( int i = 0; i < maxSize; i++ )
+      {
+        auto& item = _particleSize.at( i );
+        timeStamps[ i ] = item.first;
+        values[ i ] = item.second;
+      }
+
+      glUniform1fv( cache.getLocation( "sizeTimes" ) , maxSize ,
+                    timeStamps );
+      glUniform1fv( cache.getLocation( "sizeValues" ) , maxSize , values );
+    }
+
+    {
+      int maxSize = std::min( MAX_COLORS , static_cast<int>(_gradient.size( )));
+      glUniform1i( cache.getLocation( "gradientSize" ) , maxSize );
+
+      float timeStamps[MAX_COLORS];
+      glm::vec4 colors[MAX_COLORS];
+
+      for ( int i = 0; i < maxSize; i++ )
+      {
+        auto& item = _gradient.at( i );
+        timeStamps[ i ] = item.first;
+        colors[ i ] = item.second;
+      }
+
+      glUniform1fv( cache.getLocation( "gradientTimes" ) , maxSize ,
+                    timeStamps );
+      glUniform4fv( cache.getLocation( "gradientColors" ) , maxSize ,
+                    ( float* ) colors );
+    }
+
+    glUniform1f( cache.getLocation( "particlePreVisibility" ) ,
+                 _particleVisibility ? 1.0f : 0.0f );
+
+    // Clipping
+
+    if ( _clippingEnabled )
+    {
+      glEnable( GL_CLIP_DISTANCE0 );
+      glEnable( GL_CLIP_DISTANCE1 );
+      glUniform4fv( cache.getLocation( "plane[0]" ) , 1 ,
+                    _leftPlane->getEquation( ).data( ));
+      glUniform4fv( cache.getLocation( "plane[1]" ) , 1 ,
+                    _rightPlane->getEquation( ).data( ));
+
+      glUniform1i(
+        cache.getLocation( "isLocal[0]" ) ,
+        _leftPlane->getClippingMode( ) == reto::ClippingMode::Local );
+      glUniform1i(
+        cache.getLocation( "isLocal[1]" ) ,
+        _rightPlane->getClippingMode( ) == reto::ClippingMode::Local );
+    }
+    else
+    {
+      glDisable( GL_CLIP_DISTANCE0 );
+      glDisable( GL_CLIP_DISTANCE1 );
+    }
+
+  }
+}
\ No newline at end of file
diff --git a/visimpl/particlelab/StaticGradientModel.h b/visimpl/particlelab/StaticGradientModel.h
new file mode 100644
index 0000000000000000000000000000000000000000..6767574628edc2760d5e65ebd6a1202476b0e3df
--- /dev/null
+++ b/visimpl/particlelab/StaticGradientModel.h
@@ -0,0 +1,77 @@
+//
+// Created by gaeqs on 9/06/22.
+//
+
+#ifndef SYNCOPA_STATICPARTICLEMODEL_H
+#define SYNCOPA_STATICPARTICLEMODEL_H
+
+#include <sumrice/types.h>
+#include <reto/ClippingSystem.h>
+#include <glm/vec4.hpp>
+
+namespace visimpl
+{
+
+  class StaticGradientModel : public plab::CameraModel
+  {
+
+    std::shared_ptr< reto::ClippingPlane > _leftPlane;
+    std::shared_ptr< reto::ClippingPlane > _rightPlane;
+
+    TSizeFunction _particleSize;
+    TColorVec _gradient;
+    bool _particleVisibility;
+    bool _clippingEnabled;
+    float _time;
+
+  public:
+
+    StaticGradientModel(
+      const std::shared_ptr< plab::ICamera >& camera ,
+      const std::shared_ptr< reto::ClippingPlane >& leftPlane ,
+      const std::shared_ptr< reto::ClippingPlane >& rightPlane ,
+      const TSizeFunction& particleSize ,
+      const TColorVec& gradient ,
+      bool particleVisibility ,
+      bool clippingEnabled ,
+      float time );
+
+    const std::shared_ptr< reto::ClippingPlane >& getLeftPlane( ) const;
+
+    void
+    setLeftPlane( const std::shared_ptr< reto::ClippingPlane >& leftPlane );
+
+    const std::shared_ptr< reto::ClippingPlane >& getRightPlane( ) const;
+
+    void
+    setRightPlane( const std::shared_ptr< reto::ClippingPlane >& rightPlane );
+
+    TSizeFunction getParticleSize( ) const;
+
+    void setParticleSize( const TSizeFunction& particleSize );
+
+    const TColorVec& getGradient( ) const;
+
+    void setGradient( const TColorVec& gradient );
+
+    bool isParticleVisibility( ) const;
+
+    void setParticleVisibility( bool particleVisibility );
+
+    bool isClippingEnabled( ) const;
+
+    void enableClipping( bool enabled );
+
+    float getTime( ) const;
+
+    void setTime( float time );
+
+    void addTime( float time, float endTime );
+
+    void uploadDrawUniforms( plab::UniformCache& cache ) const override;
+
+  };
+
+}
+
+#endif //SYNCOPA_STATICPARTICLEMODEL_H
diff --git a/visimpl/prefr/ColorOperationModel.cpp b/visimpl/prefr/ColorOperationModel.cpp
deleted file mode 100644
index 00b59e8b868fea6044f5e8c5a765f812dc0f6038..0000000000000000000000000000000000000000
--- a/visimpl/prefr/ColorOperationModel.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-// Visimpl
-#include "ColorOperationModel.h"
-
-// C++
-#include <exception>
-
-namespace prefr
-{
-
-  template< class T>
-  T add(const T& lhs, const T& rhs){return lhs + rhs;}
-
-  template< class T>
-  T sub(const T& lhs, const T& rhs){return lhs - rhs;}
-
-  template< class T>
-  T mul(const T& lhs, const T& rhs){return lhs * rhs;}
-
-  template< class T>
-  T div(const T& lhs, const T& rhs){return lhs / rhs;}
-
-  ColorOperationModel::ColorOperationModel( float min, float max,
-                                            ColorOperation colorOp)
-  : Model( min, max )
-  {
-    setColorOperation(colorOp);
-  }
-
-  void ColorOperationModel::setColorOperation(ColorOperation colorOp)
-  {
-    _colorOperation = colorOp;
-
-    switch ( _colorOperation )
-    {
-      case ColorOperation::ADDITION:
-        colorop = add<glm::vec4>;
-        break;
-      case ColorOperation::SUBSTRACTION:
-        colorop = sub<glm::vec4>;
-        break;
-      case ColorOperation::MULTIPLICATION:
-        colorop = mul<glm::vec4>;
-        break;
-      case ColorOperation::DIVISION:
-        colorop = div<glm::vec4>;
-        break;
-      default:
-        {
-          const auto message = std::string("Invalid ColorOperation value ") +
-                               std::to_string(static_cast<int>(_colorOperation)) + " " +
-                               std::string(__FILE__) + ":" +
-                               std::to_string(__LINE__);
-          throw std::out_of_range(message.c_str());
-        }
-        break;
-    }
-  }
-}
diff --git a/visimpl/prefr/ColorOperationModel.h b/visimpl/prefr/ColorOperationModel.h
deleted file mode 100644
index 958b029b6b0545d85c9b36b608b87835da63ea2f..0000000000000000000000000000000000000000
--- a/visimpl/prefr/ColorOperationModel.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __VISIMPL__COLOROPERATIONMODEL__
-#define __VISIMPL__COLOROPERATIONMODEL__
-
-// Prefr
-#include <prefr/prefr.h>
-
-namespace prefr
-{
-  enum ColorOperation
-  {
-    ADDITION = 0,
-    SUBSTRACTION,
-    MULTIPLICATION,
-    DIVISION
-  };
-
-  class ColorOperationModel : public Model
-  {
-  public:
-    glm::vec4 (*colorop)(const glm::vec4& lhs, const glm::vec4& rhs);
-
-    ColorOperationModel( float min, float max,
-                         ColorOperation colorOp = ADDITION );
-
-    void setColorOperation( ColorOperation colorOp );
-
-  protected:
-    ColorOperation _colorOperation;
-  };
-}
-
-#endif /* __VISIMPL__COLOROPERATIONMODEL__ */
diff --git a/visimpl/prefr/ColorSource.cpp b/visimpl/prefr/ColorSource.cpp
deleted file mode 100644
index d0034fcf308d9665f0463657f53e574fe7918519..0000000000000000000000000000000000000000
--- a/visimpl/prefr/ColorSource.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "ColorSource.h"
-
-namespace prefr
-{
-
-  ColorSource::ColorSource( float emissionRate,
-                            const glm::vec3& position_,
-                            const glm::vec4& color_,
-                            bool still_ )
-  : Source( emissionRate, position_ )
-  , _color( color_ )
-  , _size ( 0.0f )
-  , _still( still_ )
-  {}
-
-  void ColorSource::color( const glm::vec4& color_ )
-  {
-    _color = color_;
-  }
-
-  const glm::vec4& ColorSource::color( void )
-  {
-    return _color;
-  }
-
-  void ColorSource::still( bool still_ )
-  {
-    _still = still_;
-  }
-
-  bool ColorSource::still( void )
-  {
-    return _still;
-  }
-
-  void ColorSource::size( float size_ )
-  {
-    _size = size_;
-  }
-
-  float ColorSource::size( void )
-  {
-    return _size;
-  }
-
-  bool ColorSource::emits( void ) const
-  {
-    return true;
-  }
-}
diff --git a/visimpl/prefr/ColorSource.h b/visimpl/prefr/ColorSource.h
deleted file mode 100644
index 3704de1a5e72221499150b1f806ea240e3ce413b..0000000000000000000000000000000000000000
--- a/visimpl/prefr/ColorSource.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __VISIMPL__COLOREMISSIONNODE__
-#define __VISIMPL__COLOREMISSIONNODE__
-
-// Prefr
-#include <prefr/prefr.h>
-
-namespace prefr
-{
-  class ColorSource : public Source
-  {
-  public:
-    ColorSource( float emissionRate, const glm::vec3& _position,
-                 const glm::vec4& color, bool still = false);
-
-    virtual ~ColorSource() {};
-
-    virtual void color( const glm::vec4& color );
-    virtual const glm::vec4& color( void );
-
-    virtual void still( bool still );
-    virtual bool still( void );
-
-    virtual void size( float size );
-    virtual float size( void);
-
-    virtual bool emits() const;
-
-  protected:
-    glm::vec4 _color;
-    float _size;
-    bool _still;
-  };
-}
-
-#endif /* __VISIMPL__COLOREMISSIONNODE__ */
diff --git a/visimpl/prefr/CompositeColorUpdater.cpp b/visimpl/prefr/CompositeColorUpdater.cpp
deleted file mode 100644
index 97e449daaa62e853c57ad0af6fbfb6c1bb5ab684..0000000000000000000000000000000000000000
--- a/visimpl/prefr/CompositeColorUpdater.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-// ViSimpl
-#include "CompositeColorUpdater.h"
-
-namespace prefr
-{
-  CompositeColorUpdater::CompositeColorUpdater( )
-  : Updater( )
-  {}
-
-  void CompositeColorUpdater::emitParticle( const Cluster& cluster,
-                                            const tparticle_ptr current )
-  {
-    auto model = dynamic_cast< ColorOperationModel* >( cluster.model( ));
-    auto source = dynamic_cast< ColorSource* >( cluster.source( ));
-
-    if( !current->alive( ))
-    {
-      current->set_life( model->minLife( ));
-
-      current->set_alive( true );
-
-      SampledValues values;
-      source->sample( &values );
-
-      current->set_position( values.position );
-      current->set_velocity( values.direction );
-
-    }
-  }
-
-  void CompositeColorUpdater::updateParticle( const Cluster& cluster,
-                                      const tparticle_ptr current,
-                                      float deltaTime )
-  {
-    auto model = dynamic_cast< ColorOperationModel* >( cluster.model( ));
-    auto source = dynamic_cast< ColorSource* >( cluster.source( ));
-
-    float refLife = 0;
-
-    if( current->alive( ))
-    {
-      current->set_life( std::max(0.0f, current->life( ) - deltaTime ));
-
-      refLife = 1.0f - glm::clamp( current->life( ) * model->inverseMaxLife( ),
-                                   0.0f, 1.0f );
-
-      if( !source->still( ))
-      {
-        current->set_velocityModule( model->velocity.GetValue( refLife ));
-
-        current->set_position( current->position( )
-                           + current->velocity( ) * current->velocityModule( ) *
-                                                                    deltaTime );
-      }
-
-      current->set_color( glm::clamp(
-          model->colorop( source->color( ), model->color.GetValue( refLife )),
-          0.0f, 1.0f ));
-
-      current->set_size( model->size.GetValue( refLife ) + source->size( ));
-    }
-  }
-}
diff --git a/visimpl/prefr/CompositeColorUpdater.h b/visimpl/prefr/CompositeColorUpdater.h
deleted file mode 100644
index 069a8e6a6a3905249234cc39be20a7b9e4de5729..0000000000000000000000000000000000000000
--- a/visimpl/prefr/CompositeColorUpdater.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __VISIMPL__COMPOSITECOLORUPDATER__
-#define __VISIMPL__COMPOSITECOLORUPDATER__
-
-// Prefr
-#include <prefr/prefr.h>
-
-// Visimpl
-#include "ColorOperationModel.h"
-#include "ColorSource.h"
-
-namespace prefr
-{
-  class CompositeColorUpdater : public Updater
-  {
-  public:
-    CompositeColorUpdater( );
-
-    virtual ~CompositeColorUpdater() {};
-
-    virtual void emitParticle( const Cluster& cluster, const tparticle_ptr current );
-
-    virtual void updateParticle( const Cluster& cluster, const tparticle_ptr current,
-                         float deltaTime );
-  };
-}
-
-#endif /* __VISIMPL__COMPOSITECOLORUPDATER__ */
diff --git a/visimpl/prefr/SourceMultiPosition.cpp b/visimpl/prefr/SourceMultiPosition.cpp
deleted file mode 100644
index 5e7cd3459355efe936897e645cf05d6b4d4c11c0..0000000000000000000000000000000000000000
--- a/visimpl/prefr/SourceMultiPosition.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "SourceMultiPosition.h"
-
-namespace visimpl
-{
-  SourceMultiPosition::SourceMultiPosition( void )
-  : Source( -1, glm::vec3( 0, 0, 0))
-  , _positions( nullptr )
-  , _idxTranslate( nullptr )
-  { }
-
-  void SourceMultiPosition::setIdxTranslation( const tUintUMap& idxTranslation )
-  {
-    _idxTranslate = &idxTranslation;
-  }
-
-  void SourceMultiPosition::setPositions( const tGidPosMap& positions_ )
-  {
-    _positions = &positions_;
-  }
-
-  void SourceMultiPosition::removeElements( const prefr::ParticleSet& indices )
-  {
-    _particles.removeIndices( indices );
-    restart( );
-  }
-
-  vec3 SourceMultiPosition::position( unsigned int idx )
-  {
-    assert( !_idxTranslate->empty( ));
-    assert( !_positions->empty( ) );
-
-    auto partId = _idxTranslate->find( idx );
-    assert( partId != _idxTranslate->end( ));
-
-    auto pos = _positions->find( partId->second );
-    assert( pos != _positions->end( ));
-
-    return pos->second;
-  }
-}
diff --git a/visimpl/prefr/SourceMultiPosition.h b/visimpl/prefr/SourceMultiPosition.h
deleted file mode 100644
index 29c5ac2c9baa1aae889f98cf8b5b3562c21016e9..0000000000000000000000000000000000000000
--- a/visimpl/prefr/SourceMultiPosition.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef SRC_PREFR_SOURCEMULTIPOSITION_H_
-#define SRC_PREFR_SOURCEMULTIPOSITION_H_
-
-// Visimpl
-#include "../types.h"
-
-// Prefr
-#include <prefr/prefr.h>
-
-namespace visimpl
-{
-  class SourceMultiPosition : public prefr::Source
-  {
-  public:
-    SourceMultiPosition( void );
-
-    virtual ~SourceMultiPosition( ) {};
-
-    void setIdxTranslation( const tUintUMap& idxTranslation );
-    void setPositions( const tGidPosMap& positions );
-
-    void removeElements( const prefr::ParticleSet& indices );
-
-    vec3 position( unsigned int idx );
-
-  protected:
-    const tGidPosMap* _positions;
-    const tUintUMap* _idxTranslate;
-  };
-}
-
-#endif /* SRC_PREFR_SOURCEMULTIPOSITION_H_ */
diff --git a/visimpl/prefr/UpdaterStaticPosition.cpp b/visimpl/prefr/UpdaterStaticPosition.cpp
deleted file mode 100644
index 1c8a7e4a39106e0eab0308a3d96fe15c80600d97..0000000000000000000000000000000000000000
--- a/visimpl/prefr/UpdaterStaticPosition.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-// Visimpl
-#include "UpdaterStaticPosition.h"
-#include "SourceMultiPosition.h"
-
-// C++
-#include <cmath>
-
-namespace visimpl
-{
-  using namespace prefr;
-
-  UpdaterStaticPosition::UpdaterStaticPosition( void )
-  : prefr::Updater( )
-  { }
-
-  void UpdaterStaticPosition::updateParticle( prefr::tparticle current,
-                                              float deltaTime )
-  {
-    unsigned int id = current.id( );
-    SourceMultiPosition* source = dynamic_cast<SourceMultiPosition*>( _updateConfig->source( id ));
-
-    Model* model = _updateConfig->model( id );
-
-    assert( model );
-    assert( source );
-
-    if (_updateConfig->emitted(id) && !current.alive())
-    {
-      current.set_life(0);
-
-      current.set_alive(true);
-
-      current.set_position(source->position(id));
-      current.set_velocity(glm::vec3(0, 1, 0));
-
-      current.set_velocityModule(0);
-      current.set_acceleration(glm::vec3(0, 0, 0));
-
-      _updateConfig->setEmitted(id, false);
-    }
-
-    float life = std::max(0.0f, current.life() - deltaTime);
-
-    current.set_life(life);
-
-    float refLife = 1.0f - glm::clamp(life * model->inverseMaxLife(), 0.0f, 1.0f);
-
-    // NOTE: refLife can be NAN at this point, due to life*model->inverseMaxLife()
-    // being 0*infinite. Ad that happens with you set the model life to 0 for the
-    // particle. See prefr::Model::setLife(0,0).
-    // We fix it a this point with 1 to avoid crashing further down.
-    if (std::isnan(refLife)) refLife = 1;
-
-    current.set_color(model->color.GetValue(refLife));
-    current.set_size(model->size.GetValue(refLife));
-  }
-}
-
-
diff --git a/visimpl/prefr/UpdaterStaticPosition.h b/visimpl/prefr/UpdaterStaticPosition.h
deleted file mode 100644
index 6ea65103425b97ccd9a510b3bd62348422b6186c..0000000000000000000000000000000000000000
--- a/visimpl/prefr/UpdaterStaticPosition.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2015-2020 VG-Lab/URJC.
- *
- * Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
- *
- * This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License version 3.0 as published
- * by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef SRC_PREFR_UPDATERSTATICPOSITION_H_
-#define SRC_PREFR_UPDATERSTATICPOSITION_H_
-
-#include "../types.h"
-
-#include <prefr/prefr.h>
-
-namespace visimpl
-{
-  class UpdaterStaticPosition : public prefr::Updater
-  {
-  public:
-    UpdaterStaticPosition( void );
-
-    virtual ~UpdaterStaticPosition() {};
-
-    void updateParticle( prefr::tparticle current, float deltaTime );
-  };
-}
-
-
-
-#endif /* SRC_PREFR_UPDATERSTATICPOSITION_H_ */
diff --git a/visimpl/types.h b/visimpl/types.h
index c44747d0c73da8a78757e04419f6a0d5d31a9cf9..787789e562955ce9f83c81ca4200a2f064b800b7 100644
--- a/visimpl/types.h
+++ b/visimpl/types.h
@@ -25,6 +25,7 @@
 
 #include <sumrice/sumrice.h>
 #include <reto/reto.h>
+#include <plab/core/ICamera.h>
 
 namespace visimpl
 {
@@ -34,183 +35,183 @@ namespace visimpl
 
   static inline evec3 vec4ToVec3( evec4 vec )
   {
-    return evec3( vec.x( ), vec.y( ), vec.z( ));
+    return evec3( vec.x( ) , vec.y( ) , vec.z( ));
   }
 
   static inline evec4 vec3ToVec4( evec3 vec )
   {
-    return evec4( vec.x( ), vec.y( ), vec.z( ), 1.0);
+    return evec4( vec.x( ) , vec.y( ) , vec.z( ) , 1.0 );
   }
 
-  enum tShaderParticlesType
-  {
-    T_SHADER_DEFAULT = 0,
-    T_SHADER_SOLID,
-    T_SHADER_UNDEFINED
-  };
+  typedef std::pair< vec3 , vec3 > tBoundingBox;
 
-  typedef std::pair< vec3, vec3 > tBoundingBox;
-
-  typedef std::unordered_map< unsigned int, vec3 > tGidPosMap;
-  typedef std::unordered_map< unsigned int, unsigned int > tUintUMap;
-  typedef std::unordered_multimap< unsigned int, unsigned int > tUintUMultimap;
-  typedef std::vector< std::pair< unsigned int, unsigned int >> tUintPairs;
+  typedef std::unordered_map< unsigned int , vec3 > tGidPosMap;
+  typedef std::unordered_map< unsigned int , unsigned int > tUintUMap;
+  typedef std::unordered_multimap< unsigned int , unsigned int > tUintUMultimap;
+  typedef std::vector< std::pair< unsigned int , unsigned int >> tUintPairs;
 
   enum tNeuronAttributes
   {
-    T_TYPE_MORPHO = 0,
-    T_TYPE_FUNCTION,
+    T_TYPE_MORPHO = 0 ,
+    T_TYPE_FUNCTION ,
     T_TYPE_UNDEFINED
   };
 
-  typedef std::tuple< unsigned int,
-                      unsigned int > NeuronAttributes;
+  typedef std::tuple< unsigned int ,
+    unsigned int > NeuronAttributes;
 
-  typedef std::unordered_map< unsigned int, NeuronAttributes > tNeuronAttribs;
+  typedef std::unordered_map< unsigned int , NeuronAttributes > tNeuronAttribs;
 
   enum tInitialConfig
   {
-    T_DELTATIME = 0,
-    T_STEPS_PER_SEC,
-    T_DECAY,
+    T_DELTATIME = 0 ,
+    T_STEPS_PER_SEC ,
+    T_DECAY ,
     T_SCALE
   };
 
-  typedef std::tuple< float, float, float, float > InitialConfig;
+  typedef std::tuple< float , float , float , float > InitialConfig;
 
-  typedef std::tuple< unsigned int,
-                      std::string,
-                      std::string,
-                      unsigned int > tStatsGroup;
+  typedef std::tuple< unsigned int ,
+    std::string ,
+    std::string ,
+    unsigned int > tStatsGroup;
 
   enum tTypeAttributes
   {
-    T_TYPE_VALUE = 0,
-    T_TYPE_NAME,
-    T_TYPE_LABEL,
+    T_TYPE_VALUE = 0 ,
+    T_TYPE_NAME ,
+    T_TYPE_LABEL ,
     T_TYPE_STATS
   };
 
   typedef std::vector< std::string > Strings;
   typedef std::vector< tStatsGroup > tAppStats;
 
-  typedef std::tuple< unsigned int,
-                      unsigned int,
-                      vec3,
-                      QPoint,
-                      bool
-                      > tParticleInfo;
+  typedef std::tuple< unsigned int ,
+    unsigned int ,
+    vec3 ,
+    QPoint ,
+    bool
+  > tParticleInfo;
 
   enum tParticleInfoAttribs
   {
-    T_PART_GID = 0,
-    T_PART_INTERNAL_GID,
-    T_PART_POSITION,
-    T_PART_SCREEN_POS,
-    T_PART_VALID,
+    T_PART_GID = 0 ,
+    T_PART_INTERNAL_GID ,
+    T_PART_POSITION ,
+    T_PART_SCREEN_POS ,
+    T_PART_VALID ,
     T_PART_UNDEFINED
   };
 
   static inline std::string vecToStr( const glm::vec3& vec )
   {
-    return std::string( "(" + std::to_string( vec.x) +
-                        ", " + std::to_string( vec.y) +
-                        ", " + std::to_string( vec.z) + ")");
+    return std::string( "(" + std::to_string( vec.x ) +
+                        ", " + std::to_string( vec.y ) +
+                        ", " + std::to_string( vec.z ) + ")" );
   }
 
   static inline std::string vecToStr( const Eigen::Vector3f& vec )
   {
     return std::string( "(" + std::to_string( vec.x( )) +
                         ", " + std::to_string( vec.y( )) +
-                        ", " + std::to_string( vec.z( )) + ")");
+                        ", " + std::to_string( vec.z( )) + ")" );
   }
 
   static inline Eigen::Vector3f glmToEigen( const glm::vec3& vect )
   {
-    return Eigen::Vector3f( vect.x, vect.y, vect.z );
+    return Eigen::Vector3f( vect.x , vect.y , vect.z );
   }
 
   static inline Eigen::Vector4f glmToEigen( const glm::vec4& vect )
   {
-    return Eigen::Vector4f( vect.x, vect.y, vect.z, vect.w );
+    return Eigen::Vector4f( vect.x , vect.y , vect.z , vect.w );
   }
 
   static inline glm::vec3 eigenToGLM( const Eigen::Vector3f& vect )
   {
-    return glm::vec3( vect.x( ), vect.y( ), vect.z( ) );
+    return glm::vec3( vect.x( ) , vect.y( ) , vect.z( ));
   }
 
   static inline glm::vec4 eigenToGLM( const Eigen::Vector4f& vect )
   {
-    return glm::vec4( vect.x( ), vect.y( ), vect.z( ), vect.w( ) );
+    return glm::vec4( vect.x( ) , vect.y( ) , vect.z( ) , vect.w( ));
   }
 
   static float invRGB = 1.0f / 255;
 
   static inline evec3 colorQtToEigen( const QColor& color_ )
   {
-    return evec3( std::min( 1.0f, std::max( 0.0f, color_.red( ) * invRGB )),
-                  std::min( 1.0f, std::max( 0.0f, color_.green( ) * invRGB )),
-                  std::min( 1.0f, std::max( 0.0f, color_.blue( ) * invRGB )));
+    return evec3( std::min( 1.0f , std::max( 0.0f , color_.red( ) * invRGB )) ,
+                  std::min( 1.0f ,
+                            std::max( 0.0f , color_.green( ) * invRGB )) ,
+                  std::min( 1.0f , std::max( 0.0f , color_.blue( ) * invRGB )));
   }
 
   static inline QColor colorEigenToQt( const evec3& color_ )
   {
-    return QColor( std::min( 255, std::max( 0, int( color_.x( ) * 255 ))),
-                   std::min( 255, std::max( 0, int( color_.y( ) * 255 ))),
-                   std::min( 255, std::max( 0, int( color_.z( ) * 255 ))));
+    return QColor( std::min( 255 , std::max( 0 , int( color_.x( ) * 255 ))) ,
+                   std::min( 255 , std::max( 0 , int( color_.y( ) * 255 ))) ,
+                   std::min( 255 , std::max( 0 , int( color_.z( ) * 255 ))));
   }
 
   static inline glm::vec3 floatPtrToVec3( float* floatPos )
   {
-    return glm::vec3( floatPos[ 0 ],
-                      floatPos[ 1 ],
-                      floatPos[ 2 ]);
+    return glm::vec3( floatPos[ 0 ] ,
+                      floatPos[ 1 ] ,
+                      floatPos[ 2 ] );
   }
 
   static inline glm::mat4x4 floatPtrToMat4( float* floatPos )
   {
-    return glm::mat4x4( floatPos[ 0 ], floatPos[ 1 ],
-                        floatPos[ 2 ], floatPos[ 3 ],
-                        floatPos[ 4 ], floatPos[ 5 ],
-                        floatPos[ 6 ], floatPos[ 7 ],
-                        floatPos[ 8 ], floatPos[ 9 ],
-                        floatPos[ 10 ], floatPos[ 11 ],
-                        floatPos[ 12 ], floatPos[ 13 ],
-                        floatPos[ 14 ], floatPos[ 15 ]);
+    return glm::mat4x4( floatPos[ 0 ] , floatPos[ 1 ] ,
+                        floatPos[ 2 ] , floatPos[ 3 ] ,
+                        floatPos[ 4 ] , floatPos[ 5 ] ,
+                        floatPos[ 6 ] , floatPos[ 7 ] ,
+                        floatPos[ 8 ] , floatPos[ 9 ] ,
+                        floatPos[ 10 ] , floatPos[ 11 ] ,
+                        floatPos[ 12 ] , floatPos[ 13 ] ,
+                        floatPos[ 14 ] , floatPos[ 15 ] );
   }
 
-  class Camera : public prefr::ICamera, public reto::OrbitalCameraController
+  class Camera : public plab::ICamera , public reto::OrbitalCameraController
   {
   public:
 
-    Camera( void ) : prefr::ICamera( ), reto::OrbitalCameraController( ){ }
+    Camera( void )
+      : plab::ICamera( )
+      , reto::OrbitalCameraController( )
+    { }
 
     Camera( std::string session
 #ifdef VISIMPL_USE_ZEROEQ
-        // @felix I really apologize for doing this... no other way.
-        , std::shared_ptr<zeroeq::Subscriber> subscriber = nullptr
+      // @felix I really apologize for doing this... no other way.
+      , std::shared_ptr< zeroeq::Subscriber > subscriber = nullptr
 #endif
-        ): prefr::ICamera( ), reto::OrbitalCameraController( nullptr , session
+          )
+      : plab::ICamera( )
+      , reto::OrbitalCameraController( nullptr , session
 #ifdef VISIMPL_USE_ZEROEQ
         , subscriber
 #endif
-        ){
+      )
+    {
     }
 
-    glm::vec3 PReFrCameraPosition( void )
+    glm::mat4x4 iCameraViewProjectionMatrix( ) const override
     {
-      return floatPtrToVec3( position().data() );
+      return floatPtrToMat4( _camera->projectionViewMatrix( ));
     }
 
-    glm::mat4x4 PReFrCameraViewMatrix( void )
+    glm::mat4x4 iCameraViewMatrix( ) const override
     {
-      return floatPtrToMat4( camera()->viewMatrix( ));
+      return floatPtrToMat4( _camera->viewMatrix( ));
     }
 
-    glm::mat4x4 PReFrCameraViewProjectionMatrix( void )
+    glm::vec3 iCameraPosition( ) const override
     {
-      return floatPtrToMat4( camera()->projectionViewMatrix());
+      return floatPtrToVec3( position( ).data( ));
     }
   };
 }