From 128b89518ae84d9191c18ab7ad2ea4bb7f00b5cb Mon Sep 17 00:00:00 2001
From: DEBREUVE Eric <eric.debreuve@inria.fr>
Date: Tue, 7 Jan 2020 11:23:23 +0100
Subject: [PATCH] moved frangi in independent folder

---
 brick/component/extension.py                  |  77 +--
 brick/component/glial_cmp.py                  |  14 +
 brick/component/soma.py                       |   9 -
 brick/processing/dijkstra_1_to_n.py           |   2 +-
 brick/processing/frangi3.py                   |   1 +
 brick/processing/frangi_c/makefile            |  43 --
 .../processing/frangi_c/src/__coverage__.txt  |   7 -
 .../frangi_c/src/__formatting__.txt           |   1 -
 brick/processing/frangi_c/src/data3D.h        | 338 ----------
 brick/processing/frangi_c/src/detector.cpp    | 181 ------
 brick/processing/frangi_c/src/detector.h      |  31 -
 brick/processing/frangi_c/src/eigen.cpp       | 576 ------------------
 brick/processing/frangi_c/src/eigen.h         |  37 --
 brick/processing/frangi_c/src/kernel3D.cpp    |  96 ---
 brick/processing/frangi_c/src/kernel3D.h      |  78 ---
 brick/processing/frangi_c/src/main.cpp        |  64 --
 brick/processing/frangi_c/src/processing.cpp  | 156 -----
 brick/processing/frangi_c/src/processing.h    |  14 -
 .../processing/frangi_c/src/processing_code.h | 121 ----
 brick/processing/frangi_c/src/smart_assert.h  |  41 --
 brick/processing/frangi_c/src/type_info.h     |  81 ---
 brick/processing/frangi_c/src/types.h         | 297 ---------
 brick/processing/frangi_py/frangi_3d.pxd      |  44 --
 brick/processing/frangi_py/frangi_3d.py       | 292 ---------
 nutrimorph.py                                 |  16 +-
 25 files changed, 40 insertions(+), 2577 deletions(-)
 create mode 120000 brick/processing/frangi3.py
 delete mode 100644 brick/processing/frangi_c/makefile
 delete mode 100644 brick/processing/frangi_c/src/__coverage__.txt
 delete mode 100644 brick/processing/frangi_c/src/__formatting__.txt
 delete mode 100644 brick/processing/frangi_c/src/data3D.h
 delete mode 100644 brick/processing/frangi_c/src/detector.cpp
 delete mode 100644 brick/processing/frangi_c/src/detector.h
 delete mode 100644 brick/processing/frangi_c/src/eigen.cpp
 delete mode 100644 brick/processing/frangi_c/src/eigen.h
 delete mode 100644 brick/processing/frangi_c/src/kernel3D.cpp
 delete mode 100644 brick/processing/frangi_c/src/kernel3D.h
 delete mode 100644 brick/processing/frangi_c/src/main.cpp
 delete mode 100644 brick/processing/frangi_c/src/processing.cpp
 delete mode 100644 brick/processing/frangi_c/src/processing.h
 delete mode 100644 brick/processing/frangi_c/src/processing_code.h
 delete mode 100644 brick/processing/frangi_c/src/smart_assert.h
 delete mode 100644 brick/processing/frangi_c/src/type_info.h
 delete mode 100644 brick/processing/frangi_c/src/types.h
 delete mode 100644 brick/processing/frangi_py/frangi_3d.pxd
 delete mode 100644 brick/processing/frangi_py/frangi_3d.py

diff --git a/brick/component/extension.py b/brick/component/extension.py
index 0f8a80b..2141913 100644
--- a/brick/component/extension.py
+++ b/brick/component/extension.py
@@ -31,7 +31,7 @@
 
 from __future__ import annotations
 
-# import brick.processing.frangi_py.frangi_3d as fg_
+import brick.processing.frangi3 as fg_
 import brick.processing.map_labeling as ml_
 from brick.component.glial_cmp import glial_cmp_t
 from brick.general.type import array_t, site_h
@@ -48,35 +48,6 @@ from scipy import ndimage as im_
 min_area_c = 100
 
 
-
-import ctypes as ct_
-import os.path as ph_  # Pathlib not necessary
-
-folder, script = ph_.split(__file__)
-if folder.__len__() == 0:
-    folder = "./"
-c_extension = ct_.CDLL(
-    ph_.join(folder, "..", "vesselness.so")
-)
-
-vesselness_C = c_extension.vesselness
-vesselness_C.argtypes = (
-    ct_.c_void_p,
-    ct_.c_int,
-    ct_.c_int,
-    ct_.c_int,
-    ct_.c_void_p,
-    ct_.c_float,
-    ct_.c_float,
-    ct_.c_float,
-    ct_.c_float,
-    ct_.c_float,
-    ct_.c_float,
-)
-vesselness_C.restype = None
-
-
-
 class extension_t(glial_cmp_t):
     #
     # soma_uid: connected to a soma somewhere upstream
@@ -173,7 +144,7 @@ class extension_t(glial_cmp_t):
         #
         # import os.path as ph_
 
-        # if ph_.exists("./frangi.npz"):
+        # if ph_.exists("./__runtime__/frangi.npz"):
         #     print("/!\\ Reading from precomputed data file")
         #     loaded = np_.load("./frangi.npz")
         #     enhanced_img = loaded["enhanced_img"]
@@ -185,33 +156,18 @@ class extension_t(glial_cmp_t):
             image, size=2, mode="constant", cval=0.0, origin=0
         )
 
-        preprocessed_img = preprocessed_img.astype(np_.float32)
-        enhanced_img = np_.empty(preprocessed_img.shape, dtype=np_.float32)
-        scale_map = np_.empty(preprocessed_img.shape, dtype=np_.float32)
-
-        vesselness_C(
-            preprocessed_img.ctypes.data,
-            *preprocessed_img.shape,
-            enhanced_img.ctypes.data,
-            0.1,
-            3.2,
-            1.0,
-            0.8,
-            0.5,
-            500.0,
+        enhanced_img, scale_map = fg_.FrangiEnhancement(
+            preprocessed_img,
+            scale_range=(0.1, 3.1),
+            scale_step=1.0,
+            alpha=0.8,
+            beta=0.5,
+            frangi_c=500.0,
+            bright_on_dark=True,
+            in_parallel=in_parallel,
+            method="c",
         )
 
-        # enhanced_img, scale_map = fg_.FrangiEnhancement(
-        #     preprocessed_img,
-        #     scale_range=(0.1, 3),
-        #     scale_step=1,
-        #     alpha=0.8,
-        #     beta=0.5,
-        #     frangi_c=500,
-        #     bright_on_dark=True,
-        #     in_parallel=in_parallel,
-        # )
-
         # np_.savez_compressed(
         #     "./runtime/frangi.npz", enhanced_img=enhanced_img, scale_map=scale_map
         # )
@@ -256,15 +212,6 @@ class extension_t(glial_cmp_t):
         return result.astype(np_.int8)
 
 
-def NormalizedImage(image: array_t) -> array_t:
-    #
-    middle_values = image[np_.logical_and(image > 0.0, image < image.max())]
-    image_mean = middle_values.mean()
-    result = image / image_mean
-
-    return result
-
-
 def __HysterisisImage__(image: array_t, low: float, high: float) -> array_t:
     #
     # low = 0.02
diff --git a/brick/component/glial_cmp.py b/brick/component/glial_cmp.py
index a4584e3..be5fa89 100644
--- a/brick/component/glial_cmp.py
+++ b/brick/component/glial_cmp.py
@@ -91,3 +91,17 @@ class glial_cmp_t:
     def BackReferenceSoma(self, glial_cmp: glial_cmp_t) -> None:
         #
         raise NotImplementedError
+
+
+def NormalizedImage(image: array_t) -> array_t:
+    #
+    print("This normalization does not bring anything; left as is for now to avoid the need for changing prms")
+    nonextreme_values = image[np_.logical_and(image > 0.0, image < image.max())]
+
+    if nonextreme_values.size > 0:
+        nonextreme_avg = nonextreme_values.mean()
+        result = image.astype(np_.float32) / nonextreme_avg
+    else:
+        result = image.astype(np_.float32)
+
+    return result
diff --git a/brick/component/soma.py b/brick/component/soma.py
index 7bdedba..3388dfb 100644
--- a/brick/component/soma.py
+++ b/brick/component/soma.py
@@ -238,12 +238,3 @@ def __PointsCloseTo__(
         points_as_picker = None
 
     return points, points_as_picker
-
-
-def NormalizedImage(image: array_t) -> array_t:
-    #
-    nonextreme_values = image[np_.logical_and(image > 0.0, image < image.max())]
-    nonextreme_avg = np_.mean(nonextreme_values)
-    result = image / nonextreme_avg
-
-    return result
diff --git a/brick/processing/dijkstra_1_to_n.py b/brick/processing/dijkstra_1_to_n.py
index a9cb6fe..be4f731 120000
--- a/brick/processing/dijkstra_1_to_n.py
+++ b/brick/processing/dijkstra_1_to_n.py
@@ -1 +1 @@
-../../../../../../brick/def/dijkstra-img/dijkstra_1_to_n.py
\ No newline at end of file
+/home/eric/Code/brick/def/dijkstra-img/dijkstra_1_to_n.py
\ No newline at end of file
diff --git a/brick/processing/frangi3.py b/brick/processing/frangi3.py
new file mode 120000
index 0000000..74fc34e
--- /dev/null
+++ b/brick/processing/frangi3.py
@@ -0,0 +1 @@
+/home/eric/Code/brick/def/frangi3/frangi_py/frangi3.py
\ No newline at end of file
diff --git a/brick/processing/frangi_c/makefile b/brick/processing/frangi_c/makefile
deleted file mode 100644
index 2f9fb57..0000000
--- a/brick/processing/frangi_c/makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-SRC_PATH = ./src
-SRCS = $(SRC_PATH)/detector.cpp $(SRC_PATH)/processing.cpp $(SRC_PATH)/kernel3D.cpp $(SRC_PATH)/main.cpp
-TARGET = vesselness
-
-OBJ_PATH = ./obj
-
-CC = g++ -std=c++0x
-RM = rm -f
-
-INCLUDES += -I $(SRC_PATH)
-
-#  -g    adds debugging information to the executable file
-#  -Wall turns on most, but not all, compiler warnings
-#  -pg   adds profiling information to the executable file
-#  -m64  compile for 64-bit
-#  -Wno-comment disable warnings about multiline comments
-# CFLAGS   = -Wall -Wno-reorder -m64 -fopenmp -Wno-comment -O2 -Wl,--no-as-needed
-CFLAGS   = -Wall -O2 -fopenmp
-CFLAGS  +=`pkg-config --cflags /usr/lib/pkgconfig/opencv4.pc`
-
-# LFLAGS += -Wl,--no-as-needed -pthread
-LFLAGS += -O2 -pthread -fopenmp -lm
-LFLAGS += `pkg-config --libs /usr/lib/pkgconfig/opencv4.pc`
-
-OBJS = $(SRCS:$(SRC_PATH)/%.cpp=$(OBJ_PATH)/%.o)
-
-all: $(OBJS)
-	mkdir -p $(OBJ_PATH)
-	$(CC) $(OBJS) -o $(TARGET) $(LFLAGS) $(PY_LFLAGS) $(COVERAGE) $(LIBS)
-
-py: PY_CFLAGS = -fpic
-py: PY_LFLAGS = -shared
-py: all
-	mv $(TARGET) $(TARGET).so
-
-cov: COVERAGE = -fprofile-arcs -ftest-coverage
-cov: all
-
-$(OBJ_PATH)/%.o: $(SRC_PATH)/%.cpp
-	$(CC) -c $< -o $@ $(CFLAGS) $(PY_CFLAGS) $(COVERAGE) $(INCLUDES)
-
-clean:
-	$(RM) $(OBJ_PATH)/*.o $(TARGET)
diff --git a/brick/processing/frangi_c/src/__coverage__.txt b/brick/processing/frangi_c/src/__coverage__.txt
deleted file mode 100644
index 968961f..0000000
--- a/brick/processing/frangi_c/src/__coverage__.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-gcc -Wall -fprofile-arcs -ftest-coverage cov.c
-
-Then run executable
-
-gcov cov.c
-
-Then check: cov.c.gcov
diff --git a/brick/processing/frangi_c/src/__formatting__.txt b/brick/processing/frangi_c/src/__formatting__.txt
deleted file mode 100644
index 4a0ec64..0000000
--- a/brick/processing/frangi_c/src/__formatting__.txt
+++ /dev/null
@@ -1 +0,0 @@
-astyle --style=stroustrup --recursive src/*.cpp,*.h
diff --git a/brick/processing/frangi_c/src/data3D.h b/brick/processing/frangi_c/src/data3D.h
deleted file mode 100644
index 9eb64e5..0000000
--- a/brick/processing/frangi_c/src/data3D.h
+++ /dev/null
@@ -1,338 +0,0 @@
-#pragma once
-
-#include "type_info.h"
-
-#include <iostream>
-#include <opencv2/core/core.hpp>
-#include <opencv2/highgui/highgui.hpp>
-#include <typeinfo>
-#include <string.h>
-#include "smart_assert.h"
-
-template<typename T>
-class Data3D {
-public:
-    Data3D( const cv::Vec3i& n_size = cv::Vec3i(0,0,0));
-    Data3D( const int width, const int height, const int depth );
-    Data3D( const cv::Vec3i& n_size, const T& value );
-    template <class T2>
-    Data3D( const Data3D<T2>& src );
-    const Data3D<T>& operator=( const Data3D<T>& src );
-
-    virtual ~Data3D(void) { }
-
-    inline void reset( void )
-    {
-        memset( _mat.data, 0, _size_total * sizeof(T) );
-    }
-    inline void reset( const cv::Vec3i& n_size )
-    {
-        _size = n_size;
-        long size_slice = _size[0] * _size[1];
-        _size_total = size_slice * _size[2];
-        _mat = cv::Mat_<T>( _size[2], size_slice );
-        memset( _mat.data, 0, _size_total * sizeof(T) );
-    }
-    inline void reset( const int width, const int height, const int depth )
-    {
-        _size = cv::Vec3i(width, height, depth);
-        long size_slice = _size[0] * _size[1];
-        _size_total = size_slice * _size[2];
-        _mat = cv::Mat_<T>( _size[2], size_slice );
-        memset( _mat.data, 0, _size_total * sizeof(T) );
-    }
-    void reset( const cv::Vec3i& n_size, const T& value )
-    {
-        resize( n_size );
-        for( cv::MatIterator_<T> it=_mat.begin(); it<_mat.end(); it++ )
-        {
-            (*it) = value;
-        }
-    }
-
-    void resize( const cv::Vec3i& n_size )
-    {
-        _size = n_size;
-        long size_slice = _size[0] * _size[1];
-        _size_total = size_slice * _size[2];
-        _mat = cv::Mat_<T>( _size[2], size_slice );
-    }
-
-    inline const int& SX(void) const
-    {
-        return _size[0];
-    }
-    inline const int& SY(void) const
-    {
-        return _size[1];
-    }
-    inline const int& SZ(void) const
-    {
-        return _size[2];
-    }
-    inline const int& get_width(void)  const
-    {
-        return _size[0];
-    }
-    inline const int& get_height(void) const
-    {
-        return _size[1];
-    }
-    inline const int& get_depth(void)  const
-    {
-        return _size[2];
-    }
-    inline const int& get_size_x(void) const
-    {
-        return _size[0];
-    }
-    inline const int& get_size_y(void) const
-    {
-        return _size[1];
-    }
-    inline const int& get_size_z(void) const
-    {
-        return _size[2];
-    }
-    inline const int& get_size(int i) const
-    {
-        return _size[i];
-    }
-    inline const long& get_size_total(void) const
-    {
-        return _size_total;
-    }
-    inline const cv::Vec3i& get_size(void) const
-    {
-        return _size;
-    }
-    inline const bool is_empty( void ) const
-    {
-        return get_size_total()==0;
-    }
-
-    virtual const inline T& at( const int& i ) const
-    {
-        return _mat( i );
-    }
-    virtual inline T& at( const int& i )
-    {
-        return _mat( i );
-    }
-    virtual inline const T& at( const int& x, const int& y, const int& z ) const
-    {
-        return _mat( z, y * _size[0] + x );
-    }
-    virtual inline T& at( const int& x, const int& y, const int& z )
-    {
-        return _mat( z, y * _size[0] + x );
-    }
-    virtual inline const T& at( const cv::Vec3i& pos ) const
-    {
-        return at( pos[0], pos[1], pos[2] );
-    }
-    virtual inline T& at( const cv::Vec3i& pos )
-    {
-        return at( pos[0], pos[1], pos[2] );
-    }
-
-    inline cv::Mat_<T>& getMat()
-    {
-        return _mat;
-    }
-    inline const cv::Mat_<T>& getMat() const
-    {
-        return _mat;
-    }
-    inline cv::Mat_<T> getMat( int slice ) const
-    {
-        return _mat.row(slice).reshape( 0, get_height() ).clone();
-    }
-
-    void SetFromArray( const T* array );
-    void CopyToArray( T* array );
-
-    template<typename T1, typename T2>
-    friend const Data3D<T1>& operator*=( Data3D<T1>& left, const T2& right );
-    template<typename T1, typename T2, typename T3>
-    friend bool subtract3D( const Data3D<T1>& src1, const Data3D<T2>& src2, Data3D<T3>& dst );
-    template<typename T1, typename T2, typename T3>
-    friend bool multiply3D( const Data3D<T1>& src1, const Data3D<T2>& src2, Data3D<T3>& dst );
-
-    cv::Vec<T, 2> get_min_max_value() const
-    {
-        cv::Vec<T, 2> min_max;
-        cv::Point minLoc, maxLoc;
-        cv::minMaxLoc( _mat, NULL, NULL, &minLoc, &maxLoc);
-        min_max[0] = _mat( minLoc );
-        min_max[1] = _mat( maxLoc );
-        return min_max;
-    }
-
-public:
-    /* copy data of dimension i to a new Image3D structure
-       e.g. this is useful when trying to visualize vesselness which is
-       a multidimensional data structure
-       Yuchen: p.s. I have no idea how to move the funciton body out the
-       class definition nicely. Let me figure it later maybe. */
-    template<typename T2>
-    void copyDimTo( Data3D<T2>& dst, int dim ) const
-    {
-        dst.reset( this->get_size() );
-        int x, y, z;
-        for( z=0; z<get_size_z(); z++ ) for( y=0; y<get_size_y(); y++ ) for( x=0; x<get_size_x(); x++ ) {
-                    dst.at(x,y,z) = this->at(x,y,z)[dim];
-                }
-    }
-
-
-    // return true if a index is valide for the data
-    inline bool isValid( const int& x, const int& y, const int& z ) const
-    {
-        return ( x>=0 && x<get_size_x() &&
-                 y>=0 && y<get_size_y() &&
-                 z>=0 && z<get_size_z() );
-    }
-    inline bool isValid( const cv::Vec3i& v ) const
-    {
-        return isValid( v[0], v[1], v[2] );
-    }
-
-    inline const T* getData(void) const
-    {
-        return (T*) getMat().data;
-    }
-
-    inline T* getData(void)
-    {
-        return (T*) getMat().data;
-    }
-
-protected:
-    cv::Vec3i _size;
-    long _size_total;
-    cv::Mat_<T> _mat;
-};
-
-
-// Default Constructor
-template <typename T>
-Data3D<T>::Data3D( const cv::Vec3i& n_size )
-{
-    reset(n_size);
-}
-template <typename T>
-Data3D<T>::Data3D( const int width, const int height, const int depth )
-{
-    reset(width, height, depth);
-}
-
-// Constructor with size and value
-template <typename T>
-Data3D<T>::Data3D( const cv::Vec3i& n_size, const T& value )
-{
-    reset(n_size, value);
-}
-
-
-// Copy Constructor
-template<typename T>
-template<typename T2>
-Data3D<T>::Data3D( const Data3D<T2>& src )
-{
-    // resize
-    this->resize( src.get_size() );
-    // copy the data over
-    cv::MatIterator_<T>       this_it;
-    cv::MatConstIterator_<T2> src_it;
-    for( this_it = this->getMat().begin(), src_it = src.getMat().begin();
-            this_it < this->getMat().end(),   src_it < src.getMat().end();
-            this_it++, src_it++ ) {
-        // Yuchen: The convertion from T2 to T may be unsafe
-        *(this_it) = T( *(src_it) );
-    }
-}
-
-
-template<typename T>
-const Data3D<T>& Data3D<T>::operator=( const Data3D<T>& src )
-{
-    // resize
-    this->resize( src.get_size() );
-
-    // copy the data over
-    cv::MatIterator_<T>       this_it;
-    cv::MatConstIterator_<T> src_it;
-    for( this_it = this->getMat().begin(), src_it = src.getMat().begin();
-            this_it < this->getMat().end(),   src_it < src.getMat().end();
-            this_it++, src_it++ ) {
-        *(this_it) = *(src_it);
-    }
-
-    return *this;
-}
-
-
-template <typename T>
-void Data3D<T>::SetFromArray( const T* array )
-{
-    memcpy(_mat.data, array, _size_total * sizeof(T));
-}
-
-template <typename T>
-void Data3D<T>::CopyToArray( T* array )
-{
-    memcpy(array, _mat.data, _size_total * sizeof(T));
-}
-
-//////////////////////////////////////////////////////////////////////
-// Operator Overloading and other friend functions
-
-template<typename T, typename T2>
-const Data3D<T>& operator*=( Data3D<T>& left, const T2& right )
-{
-    left._mat*=right;
-    return left;
-}
-
-template<typename T1, typename T2, typename T3>
-bool subtract3D( const Data3D<T1>& src1, const Data3D<T2>& src2, Data3D<T3>& dst )
-{
-    smart_return( src1.get_size()==src2.get_size(), "Sizes should match.", false);
-
-    if( dst.get_size() != src1.get_size() ) {
-        dst.reset( src1.get_size() );
-    }
-
-    int x, y, z;
-    for( z=0; z<src1.get_size_z(); z++ ) {
-        for( y=0; y<src1.get_size_y(); y++ ) {
-            for( x=0; x<src1.get_size_x(); x++ ) {
-                dst.at(x,y,z) = T3(src1.at(x,y,z) - src2.at(x,y,z));
-            }
-        }
-    }
-    return true;
-}
-
-
-template<typename T1, typename T2, typename T3>
-bool multiply3D( const Data3D<T1>& src1, const Data3D<T2>& src2, Data3D<T3>& dst )
-{
-    smart_return_false( src1.get_size()==src2.get_size(),
-                        "Source sizes are supposed to be cv::Matched.");
-
-    if( dst.get_size() != src1.get_size() ) {
-        dst.reset( src1.get_size() );
-    }
-
-    int x, y, z;
-    for( z=0; z<src1.get_size_z(); z++ ) {
-        for( y=0; y<src1.get_size_y(); y++ ) {
-            for( x=0; x<src1.get_size_x(); x++ ) {
-                dst.at(x,y,z) = src1.at(x,y,z) * src2.at(x,y,z);
-            }
-        }
-    }
-    return true;
-}
diff --git a/brick/processing/frangi_c/src/detector.cpp b/brick/processing/frangi_c/src/detector.cpp
deleted file mode 100644
index 6d68f8d..0000000
--- a/brick/processing/frangi_c/src/detector.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-#include "detector.h"
-#include "data3D.h"
-#include "processing_code.h"
-#include "types.h"
-#include "eigen.cpp" // Otherwise the template mechanism does not work. TODO: solve this
-
-using namespace std;
-
-Vesselness hessien_thread_func( const Data3D<float>& src,
-                                const int& x, const int& y, const int& z,
-                                const float& alpha, const float& beta, const float& gamma )
-{
-
-    ////////////////////////////////////////////////////////////////////
-    // The following are being computed in this function
-    // 1) derivative of images;
-    // 2) Hessian matrix;
-    // 3) Eigenvalue decomposition;
-    // 4) vesselness measure.
-
-    // 1) derivative of the image
-    float im_dx2 = -2.0f * src.at(x,y,z) + src.at(x-1,y,z) + src.at(x+1,y,z);
-    float im_dy2 = -2.0f * src.at(x,y,z) + src.at(x,y-1,z) + src.at(x,y+1,z);
-    float im_dz2 = -2.0f * src.at(x,y,z) + src.at(x,y,z-1) + src.at(x,y,z+1);
-    // 1) derivative of the image (alternative approach, the one above is more accurate)
-    //float im_dx2 = -0.5f * src.at(x,y,z) + 0.25f * src.at(x-2,y,z) + 0.25f * src.at(x+2,y,z);
-    //float im_dy2 = -0.5f * src.at(x,y,z) + 0.25f * src.at(x,y-2,z) + 0.25f * src.at(x,y+2,z);
-    //float im_dz2 = -0.5f * src.at(x,y,z) + 0.25f * src.at(x,y,z-2) + 0.25f * src.at(x,y,z+2);
-
-    float im_dxdy = (
-                        + src.at(x-1, y-1, z)
-                        + src.at(x+1, y+1, z)
-                        - src.at(x-1, y+1, z)
-                        - src.at(x+1, y-1, z) ) * 0.25f;
-    float im_dxdz = (
-                        + src.at(x-1, y, z-1)
-                        + src.at(x+1, y, z+1)
-                        - src.at(x+1, y, z-1)
-                        - src.at(x-1, y, z+1) ) * 0.25f;
-    float im_dydz = (
-                        + src.at(x, y-1, z-1)
-                        + src.at(x, y+1, z+1)
-                        - src.at(x, y+1, z-1)
-                        - src.at(x, y-1, z+1) ) * 0.25f;
-
-    // 3) Eigenvalue decomposition
-    // Reference: http://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices
-    // Given a real symmetric 3x3 matrix Hessian, compute the eigenvalues
-    const float Hessian[6] = {im_dx2, im_dxdy, im_dxdz, im_dy2, im_dydz, im_dz2};
-
-    float eigenvalues[3];
-    float eigenvectors[3][3];
-    eigen_decomp( Hessian, eigenvalues, eigenvectors );
-
-    // order eigenvalues so that |lambda1| < |lambda2| < |lambda3|
-    int i=0, j=1, k=2;
-//     if( abs(eigenvalues[i]) > abs(eigenvalues[j]) ) std::swap( i, j );
-//     if( abs(eigenvalues[i]) > abs(eigenvalues[k]) ) std::swap( i, k );
-//     if( abs(eigenvalues[j]) > abs(eigenvalues[k]) ) std::swap( j, k );
-
-    // 4) vesselness measure
-    Vesselness vn;
-    // vesselness value
-    if( eigenvalues[j] > 0 || eigenvalues[k] > 0 ) {
-        vn.rsp = 0.0f;
-    }
-    else {
-        float lmd1 = abs( eigenvalues[i] );
-        float lmd2 = abs( eigenvalues[j] );
-        float lmd3 = abs( eigenvalues[k] );
-
-        float A = (lmd3>1e-5) ? lmd2/lmd3 : 0;
-        float B = (lmd2*lmd3>1e-5) ? lmd1 / sqrt( lmd2*lmd3 ) : 0;
-        float S = sqrt( lmd1*lmd1 + lmd2*lmd2 + lmd3*lmd3 );
-        vn.rsp = ( 1.0f-exp(-A*A/alpha) )* exp( B*B/beta ) * ( 1-exp(-S*S/gamma) );
-    }
-
-    // orientation of vesselness is corresponding to the eigenvector of the
-    // smallest eigenvalue
-    for( int d=0; d<3; d++ ) {
-        vn.dir[d] = eigenvectors[i][d];
-    }
-
-    return vn;
-}
-
-
-
-bool VesselDetector::hessien( const Data3D<float>& src, Data3D<Vesselness>& dst,
-                              int ksize, float sigma,
-                              float alpha, float beta, float gamma )
-{
-    if( ksize!=0 && sigma<1e-3 ) { // sigma is not set
-        sigma = 0.15f * ksize + 0.35f;
-    }
-    else if ( ksize==0 && sigma>1e-3 ) { // size is not set
-        ksize = int( 6*sigma+1 );
-        // make sure size is an odd number
-        if ( ksize%2==0 ) ksize++;
-    }
-    else {
-        std::cerr << "At lease size or sigma has to be set." << std::endl;
-        return false;
-    }
-
-    Data3D<float> im_blur;
-    bool flag = ImageProcessing::GaussianBlur3D( src, im_blur, ksize, sigma );
-    smart_return( flag, "Gaussian Blur Failed.", false );
-
-    im_blur *= std::pow(sigma, 1.2); //Normalizing for different scale
-
-    dst.reset( im_blur.get_size(), Vesselness(0.0f) );
-
-    #pragma omp parallel
-    {
-        #pragma omp for
-        for( int z = 1; z < src.get_size_z()-1; z++ ) {
-            for( int y = 1; y < src.get_size_y()-1; y++ ) {
-                for( int x = 1; x < src.get_size_x()-1; x++ ) {
-                    dst.at(x, y, z) = hessien_thread_func( im_blur, x, y, z, alpha, beta, gamma);
-                }
-            }
-        }
-    }
-
-    return true;
-}
-
-
-
-int VesselDetector::compute_vesselness(
-    const Data3D<float>& src,
-    Data3D<Vesselness_Sig>& dst,
-    float sigma_from, float sigma_to, float sigma_step,
-    float alpha, float beta, float gamma )
-{
-    std::cout << "Computing Vesselness, it will take a while... " << std::endl;
-    std::cout << "Vesselness will be computed from sigma = " << sigma_from << " to sigma = " << sigma_to << std::endl;
-
-    dst.reset( src.get_size() ); // reszie data, and it will also be clear to zero
-
-    // Error for input parameters
-    smart_return( sigma_from < sigma_to,
-                  "sigma_from should be smaller than sigma_to ", 0 );
-    smart_return( sigma_step > 0,
-                  "sigma_step should be greater than 0 ", 0 );
-
-    int x,y,z;
-    float max_sigma = sigma_from;
-    float min_sigma = sigma_to;
-
-    Data3D<Vesselness> temp;
-    for( float sigma = sigma_from; sigma < sigma_to; sigma += sigma_step ) {
-        cout << '\r' << "Vesselness for sigma = " << sigma << "    " << "\b\b\b\b";
-        cout.flush();
-
-        VesselDetector::hessien( src, temp, 0, sigma, alpha, beta, gamma );
-
-        const int margin = 1;
-        for( z=margin; z<src.get_size_z()-margin; z++ ) {
-            for( y=margin; y<src.get_size_y()-margin; y++ ) {
-                for( x=margin; x<src.get_size_x()-margin; x++ ) {
-                    // Update vesselness if the new response is greater
-                    if( dst.at(x, y, z).rsp < temp.at(x, y, z).rsp ) {
-                        dst.at(x, y, z).rsp = temp.at(x, y, z).rsp;
-                        dst.at(x, y, z).dir = temp.at(x, y, z).dir;
-                        dst.at(x, y, z).sigma = sigma;
-                        max_sigma = std::max( sigma, max_sigma );
-                        min_sigma = std::min( sigma, min_sigma );
-                    }
-                }
-            }
-        }
-    }
-
-    std::cout << std::endl << "The range for sigma is [";
-    std::cout << min_sigma << ", " << max_sigma << "]" << std::endl;
-    std::cout << "Done. " << std::endl << std::endl;
-
-    return 0;
-}
diff --git a/brick/processing/frangi_c/src/detector.h b/brick/processing/frangi_c/src/detector.h
deleted file mode 100644
index e08e6eb..0000000
--- a/brick/processing/frangi_c/src/detector.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef VESSELDETECTOR_H
-#define VESSELDETECTOR_H
-
-#include "types.h"
-
-template<typename T> class Data3D;
-
-class Vesselness;
-class Vesselness_Sig;
-class Vesselness_Nor;
-class Vesselness_All;
-
-namespace VesselDetector {
-bool hessien(
-    const Data3D<float>& src, Data3D<Vesselness>& dst,
-    int ksize, float sigma,
-    float alpha, float beta, float gamma );
-
-int compute_vesselness(
-    const Data3D<float>& src,
-    Data3D<Vesselness_Sig>& dst,
-    float sigma_from, float sigma_to, float sigma_step,
-    float alpha = 1.0e-1f,
-    float beta  = 5.0e0f,
-    float gamma = 3.5e5f );
-};
-
-namespace VD = VesselDetector;
-namespace VF = VesselDetector;
-
-#endif
diff --git a/brick/processing/frangi_c/src/eigen.cpp b/brick/processing/frangi_c/src/eigen.cpp
deleted file mode 100644
index 71ab97d..0000000
--- a/brick/processing/frangi_c/src/eigen.cpp
+++ /dev/null
@@ -1,576 +0,0 @@
-#include "eigen.h"
-
-/* Compute the eigen value decomposition of a 3 by 3 symetric matrix
-Input:
-A = [ A11  A12  A13     = [ A[0]  A[1]  A[2]
-A21  A22  A23          0    A[3]  A[4]
-A31  A32  A33 ];       0     0    A[5] ];
-Output:
-eigenvalues, eigenvectors
-
-Reference: http://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices
-*/
-#include <cmath>
-#include <assert.h>
-#include <algorithm>
-#include <iostream>
-// #include <opencv2/core/types_c.h>
-// #include <opencv2/core/core_c.h>
-
-
-#if !defined(SmallEpsilon) && !defined(BigEpsilon)
-#define SmallEpsilon 1.0e-18
-#define BigEpsilon 1.0e-4
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#include "math.h"
-#ifdef MAX
-#undef MAX
-#endif
-#define MAX(a, b) ((a)>(b)?(a):(b))
-#define n 3
-
-// address/from/source: https://github.com/fethallah/neurons/blob/master/frangi_filter_version2a/eig3volume.c
-
-/* Eigen decomposition code for symmetric 3x3 matrices, copied from the public
- * domain Java Matrix library JAMA. */
-static float hypot2(float x, float y) { return (float) sqrt(x*x+y*y); }
-
-__inline float absd(float val){ if(val>0){ return val;} else { return -val;} };
-
-/* Symmetric Householder reduction to tridiagonal form. */
-static void tred2(float V[n][n], float d[n], float e[n]) {
-
-/*  This is derived from the Algol procedures tred2 by */
-/*  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for */
-/*  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding */
-/*  Fortran subroutine in EISPACK. */
-
-//     std::cout << "Entering tred2" << std::endl;
-
-    int i, j, k;
-    float scale;
-    float f, g, h;
-    float hh;
-    for (j = 0; j < n; j++) {d[j] = V[n-1][j]; }
-
-    /* Householder reduction to tridiagonal form. */
-
-    for (i = n-1; i > 0; i--) {
-        /* Scale to avoid under/overflow. */
-        scale = 0.0;
-        h = 0.0;
-        for (k = 0; k < i; k++) { scale = scale + fabs(d[k]); }
-        if (scale == 0.0) {
-            e[i] = d[i-1];
-            for (j = 0; j < i; j++) { d[j] = V[i-1][j]; V[i][j] = 0.0;  V[j][i] = 0.0; }
-        } else {
-
-            /* Generate Householder vector. */
-
-            for (k = 0; k < i; k++) { d[k] /= scale; h += d[k] * d[k]; }
-            f = d[i-1];
-            g = sqrt(h);
-            if (f > 0) { g = -g; }
-            e[i] = scale * g;
-            h = h - f * g;
-            d[i-1] = f - g;
-            for (j = 0; j < i; j++) { e[j] = 0.0; }
-
-            /* Apply similarity transformation to remaining columns. */
-
-            for (j = 0; j < i; j++) {
-                f = d[j];
-                V[j][i] = f;
-                g = e[j] + V[j][j] * f;
-                for (k = j+1; k <= i-1; k++) { g += V[k][j] * d[k]; e[k] += V[k][j] * f; }
-                e[j] = g;
-            }
-            f = 0.0;
-            for (j = 0; j < i; j++) { e[j] /= h; f += e[j] * d[j]; }
-            hh = f / (h + h);
-            for (j = 0; j < i; j++) { e[j] -= hh * d[j]; }
-            for (j = 0; j < i; j++) {
-                f = d[j]; g = e[j];
-                for (k = j; k <= i-1; k++) { V[k][j] -= (f * e[k] + g * d[k]); }
-                d[j] = V[i-1][j];
-                V[i][j] = 0.0;
-            }
-        }
-        d[i] = h;
-    }
-
-    /* Accumulate transformations. */
-
-    for (i = 0; i < n-1; i++) {
-        V[n-1][i] = V[i][i];
-        V[i][i] = 1.0;
-        h = d[i+1];
-        if (h != 0.0) {
-            for (k = 0; k <= i; k++) { d[k] = V[k][i+1] / h;}
-            for (j = 0; j <= i; j++) {
-                g = 0.0;
-                for (k = 0; k <= i; k++) { g += V[k][i+1] * V[k][j]; }
-                for (k = 0; k <= i; k++) { V[k][j] -= g * d[k]; }
-            }
-        }
-        for (k = 0; k <= i; k++) { V[k][i+1] = 0.0;}
-    }
-    for (j = 0; j < n; j++) { d[j] = V[n-1][j]; V[n-1][j] = 0.0; }
-    V[n-1][n-1] = 1.0;
-    e[0] = 0.0;
-
-//     std::cout << "Leaving tred2" << std::endl;
-}
-
-/* Symmetric tridiagonal QL algorithm. */
-static void tql2(float V[n][n], float d[n], float e[n]) {
-
-/*  This is derived from the Algol procedures tql2, by */
-/*  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for */
-/*  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding */
-/*  Fortran subroutine in EISPACK. */
-
-//     std::cout << "Entering tql2" << std::endl;
-
-    int i, j, k, l, m;
-    float f;
-    float tst1;
-    float eps;
-    int iter;
-    float g, p, r;
-    float dl1, h, c, c2, c3, el1, s, s2;
-
-    for (i = 1; i < n; i++) { e[i-1] = e[i]; }
-    e[n-1] = 0.0;
-
-    f = 0.0;
-    tst1 = 0.0;
-    eps = pow(2.0, -52.0);
-    for (l = 0; l < n; l++) {
-
-        /* Find small subdiagonal element */
-
-        tst1 = MAX(tst1, fabs(d[l]) + fabs(e[l]));
-        m = l;
-        while (m < n) {
-            if (fabs(e[m]) <= eps*tst1) { break; }
-            m++;
-        }
-
-        /* If m == l, d[l] is an eigenvalue, */
-        /* otherwise, iterate. */
-
-        if (m > l) {
-            iter = 0;
-            do {
-                iter = iter + 1;  /* (Could check iteration count here.) */
-                /* Compute implicit shift */
-                g = d[l];
-                p = (d[l+1] - g) / (2.0 * e[l]);
-                r = hypot2(p, 1.0);
-                if (p < 0) { r = -r; }
-                d[l] = e[l] / (p + r);
-                d[l+1] = e[l] * (p + r);
-                dl1 = d[l+1];
-                h = g - d[l];
-                for (i = l+2; i < n; i++) { d[i] -= h; }
-                f = f + h;
-                /* Implicit QL transformation. */
-                p = d[m]; c = 1.0; c2 = c; c3 = c;
-                el1 = e[l+1]; s = 0.0; s2 = 0.0;
-                for (i = m-1; i >= l; i--) {
-                    c3 = c2;
-                    c2 = c;
-                    s2 = s;
-                    g = c * e[i];
-                    h = c * p;
-                    r = hypot2(p, e[i]);
-                    e[i+1] = s * r;
-                    s = e[i] / r;
-                    c = p / r;
-                    p = c * d[i] - s * g;
-                    d[i+1] = h + s * (c * g + s * d[i]);
-                    /* Accumulate transformation. */
-                    for (k = 0; k < n; k++) {
-                        h = V[k][i+1];
-                        V[k][i+1] = s * V[k][i] + c * h;
-                        V[k][i] = c * V[k][i] - s * h;
-                    }
-                }
-                p = -s * s2 * c3 * el1 * e[l] / dl1;
-                e[l] = s * p;
-                d[l] = c * p;
-
-                /* Check for convergence. */
-            } while (fabs(e[l]) > eps*tst1);
-        }
-        d[l] = d[l] + f;
-        e[l] = 0.0;
-    }
-
-    /* Sort eigenvalues and corresponding vectors. */
-    for (i = 0; i < n-1; i++) {
-        k = i;
-        p = d[i];
-        for (j = i+1; j < n; j++) {
-            if (d[j] < p) {
-                k = j;
-                p = d[j];
-            }
-        }
-        if (k != i) {
-            d[k] = d[i];
-            d[i] = p;
-            for (j = 0; j < n; j++) {
-                p = V[j][i];
-                V[j][i] = V[j][k];
-                V[j][k] = p;
-            }
-        }
-    }
-
-//     std::cout << "Leaving tql2" << std::endl;
-}
-
-void eigen_decomposition(float A[n][n], float V[n][n], float d[n]) {
-    float e[n];
-    float da[3];
-    float dt, dat;
-    float vet[3];
-    int i, j;
-
-//     std::cout << "Entering egien_decompositiom" << std::endl;
-
-    for (i = 0; i < n; i++) {
-        for (j = 0; j < n; j++) {
-            V[i][j] = A[i][j];
-        }
-    }
-    tred2(V, d, e);
-    tql2(V, d, e);
-
-    /* Sort the eigen values and vectors by abs eigen value */
-    da[0]=absd(d[0]); da[1]=absd(d[1]); da[2]=absd(d[2]);
-    if((da[0]>=da[1])&&(da[0]>da[2]))
-    {
-        dt=d[2];   dat=da[2];    vet[0]=V[0][2];    vet[1]=V[1][2];    vet[2]=V[2][2];
-        d[2]=d[0]; da[2]=da[0];  V[0][2] = V[0][0]; V[1][2] = V[1][0]; V[2][2] = V[2][0];
-        d[0]=dt;   da[0]=dat;    V[0][0] = vet[0];  V[1][0] = vet[1];  V[2][0] = vet[2];
-    }
-    else if((da[1]>=da[0])&&(da[1]>da[2]))
-    {
-        dt=d[2];   dat=da[2];    vet[0]=V[0][2];    vet[1]=V[1][2];    vet[2]=V[2][2];
-        d[2]=d[1]; da[2]=da[1];  V[0][2] = V[0][1]; V[1][2] = V[1][1]; V[2][2] = V[2][1];
-        d[1]=dt;   da[1]=dat;    V[0][1] = vet[0];  V[1][1] = vet[1];  V[2][1] = vet[2];
-    }
-    if(da[0]>da[1])
-    {
-        dt=d[1];   dat=da[1];    vet[0]=V[0][1];    vet[1]=V[1][1];    vet[2]=V[2][1];
-        d[1]=d[0]; da[1]=da[0];  V[0][1] = V[0][0]; V[1][1] = V[1][0]; V[2][1] = V[2][0];
-        d[0]=dt;   da[0]=dat;    V[0][0] = vet[0];  V[1][0] = vet[1];  V[2][0] = vet[2];
-    }
-
-//     std::cout << "Leaving egien_decompositiom" << std::endl;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/*
-template<typename T=float>
-inline void normalize( T v[3] )
-{
-    T length = 0;
-    for( int i=0; i<3; i++ ) {
-        length += v[i] * v[i];
-    }
-//     assert( length > SmallEpsilon && "Cannot normalized zero vector" );
-    if ( length <= SmallEpsilon )
-        return;
-
-    length = sqrt( length );
-    for( int i=0; i<3; i++ ) {
-        v[i] /= length;
-    }
-}
-
-template<typename T=float>
-inline void cross_product( const T v1[3], const T v2[3], T v3[3] )
-{
-    v3[0] = v1[1] * v2[2] - v1[2] * v2[1];
-    v3[1] = v1[2] * v2[0] - v1[0] * v2[2];
-    v3[2] = v1[0] * v2[1] - v1[1] * v2[0];
-    normalize( v3 );
-}
-
-template<typename T=float>
-void normal_vectors(  const T v1[3], T v2[3], T v3[3] )
-{
-    // an arbitrary combination of the following two vectors
-    // is a normal to v1
-    // alpha * (-v1[1], v1[0], 0) + beta * (0, -v1[2], v[1])
-
-    if( abs(v1[0])>BigEpsilon || abs(v1[1])>BigEpsilon ) {
-        v2[0] = -v1[1];
-        v2[1] =  v1[0];
-        v2[2] =  0;
-    }
-    else {
-        v2[0] =  0;
-        v2[1] = -v1[2];
-        v2[2] =  v1[1];
-    }
-
-    normalize( v2 );
-
-    cross_product( v1, v2, v3 );
-}
-*/
-
-template<typename T=float>
-void eigen_decomp( const T A[6], T eigenvalues[3], T eigenvectors[3][3] )
-{
-    float Asym[n][n];
-    Asym[0][0] = A[0]; Asym[0][1] = A[1]; Asym[0][2] = A[2];
-    Asym[1][0] = A[1]; Asym[1][1] = A[3]; Asym[1][2] = A[4];
-    Asym[2][0] = A[2]; Asym[2][1] = A[4]; Asym[2][2] = A[5];
-
-    /* Function below sorts the eigen values and vectors by abs eigen value */
-    eigen_decomposition(Asym, eigenvectors, eigenvalues);
-
-    return;
-
-//     static CvMat mat, *eigenVec, *eigenVal;
-//     static float Ain1D[9];
-//
-//     int cnt = 0;
-//     Ain1D[cnt++] = A[0];
-//     Ain1D[cnt++] = A[1];
-//     Ain1D[cnt++] = A[2];
-//     Ain1D[cnt++] = A[1];
-//     Ain1D[cnt++] = A[3];
-//     Ain1D[cnt++] = A[4];
-//     Ain1D[cnt++] = A[2];
-//     Ain1D[cnt++] = A[4];
-//     Ain1D[cnt++] = A[5];
-//
-//     int i;
-//     std::cout << std::endl;
-//     for (i = 0; i < 9; i++) {
-//         std::cout << Ain1D[i] << " ";
-//         if ((i == 1) || (i == 4))
-//             std::cout << std::endl;
-//     }
-//     std::cout << std::endl << std::endl;
-//
-//     mat = cvMat(3, 3, CV_32FC1, Ain1D);
-//
-//     cvEigenVV(&mat, eigenVec, eigenVal, 1e-300);
-//
-//     for(int i=0;i < 3;i++){
-//         eigenvalues[i] = cvmGet(eigenVal,i,0); //Fetching Eigen Value
-//
-//         for(int j=0;j < 3;j++){
-//             eigenvectors[i][j] = cvmGet(eigenVec,i,j); //Fetching each component of Eigenvector i
-//         }
-//     }
-//
-//     return;
-
-/*
-    const T& A11 = A[0];
-    const T& A12 = A[1];
-    const T& A13 = A[2];
-    const T& A22 = A[3];
-    const T& A23 = A[4];
-    const T& A33 = A[5];
-
-    T& eig1 = eigenvalues[0];
-    T& eig2 = eigenvalues[1];
-    T& eig3 = eigenvalues[2];
-
-    T p1 = A12 * A12 + A13 * A13 + A23 * A23;
-    if( p1 < SmallEpsilon ) { // if A is diagonal
-        eig1 = A11;
-        eig2 = A22;
-        eig3 = A33;
-        memset( eigenvectors, 0, sizeof(T) * 9 );
-        eigenvectors[0][0] = eigenvectors[1][1] = eigenvectors[2][2] = 1;
-    }
-    else {   // if A is not diagonal
-        // Compute 1/3 of the trace of matrix A: trace(A)/3
-        T q = ( A11 + A22 + A33 ) / 3;
-        T p2 = (A11-q)*(A11-q) + (A22-q)*(A22-q) + (A33-q)*(A33-q) + 2 * p1;
-        T p = sqrt( p2 / 6);
-
-        // Construct matrix B
-        // B = (1 / p) * (A - q * I), where I is the identity matrix
-        T B11 = (1 / p) * (A11-q);
-        T B12 = (1 / p) * A12;
-        T& B21 = B12;
-        T B13 = (1 / p) * A13;
-        T& B31 = B13;
-        T B22 = (1 / p) * (A22-q);
-        T B23 = (1 / p) * A23;
-        T& B32 = B23;
-        T B33 = (1 / p) * (A33-q);
-
-        // Determinant of a 3 by 3 matrix B
-        // Reference: http://www.mathworks.com/help/aeroblks/determinantof3x3matrix.html
-        T detB = B11*(B22*B33-B23*B32) - B12*(B21*B33-B23*B31) + B13*(B21*B32-B22*B31);
-
-        // In exact arithmetic for a symmetric matrix  -1 <= r <= 1
-        // but computation error can leave it slightly outside this range.
-        T r = detB / 2;
-        T phi;
-        const T M_PI3 = T(3.14159265 / 3);
-        if( r <= -1.0f ) {
-            phi = M_PI3;
-        }
-        else if (r >= 1.0f)
-            phi = 0;
-        else {
-            phi = acos(r) / 3;
-        }
-
-        // The eigenvalues satisfy eig3 <= eig2 <= eig1
-        // Notice that: trace(A) = eig1 + eig2 + eig3
-        eig1 = q + 2 * p * cos( phi );
-        eig3 = q + 2 * p * cos( phi + 2 * M_PI3 );
-        eig2 = 3 * q - eig1 - eig3;
-
-        // make sure that |eig1| >= |eig2| >= |eig3|
-        if( abs(eig1) < abs(eig2) ) std::swap(eig1, eig2);
-        if( abs(eig2) < abs(eig3) ) std::swap(eig2, eig3);
-        if( abs(eig1) < abs(eig2) ) std::swap(eig1, eig2);
-
-        // If eig1 is too small, it is not worth to compute the eigenvectors
-        if( abs(eig1) < BigEpsilon ) {
-            memset( eigenvectors, 0, sizeof(T) * 9 );
-            eigenvectors[0][0] = eigenvectors[1][1] = eigenvectors[2][2] = 1;
-        }
-
-        // Compute the corresponding eigenvectors
-        // Reference: [Cayley-Hamilton_theorem](http://en.wikipedia.org/wiki/Cayley-Hamilton_theorem)
-        // If eig1, eig2, eig3 are the distinct eigenvalues of the matrix A;
-        // that is: eig1 != eig2 != eig3. Then
-        // (A - eig1 * I)(A - eig2 * I)(A - eig3 * I) = 0
-        // Thus the columns of the product of any two of these matrices
-        // will contain an eigenvector for the third eigenvalue.
-        else if( abs(eig1-eig2)<BigEpsilon && abs(eig2-eig3)<BigEpsilon ) {
-            memset( eigenvectors, 0, sizeof(T) * 9 );
-            eigenvectors[0][0] = eigenvectors[1][1] = eigenvectors[2][2] = 1;
-        }
-        else if ( abs(eig1-eig2)<BigEpsilon ) {
-            // tested
-            eigenvector_from_value( A, eig1, eig2, eigenvectors[2] );
-            normal_vectors( eigenvectors[2], eigenvectors[1], eigenvectors[0] );
-        }
-        else if ( abs(eig2-eig3)<BigEpsilon ) {
-            // tested
-            eigenvector_from_value( A, eig2, eig3, eigenvectors[0] );
-            normal_vectors( eigenvectors[0], eigenvectors[1], eigenvectors[2] );
-        }
-        else {
-            // eig1!=eig2 && eig2!=eig3 && eig1!=eig3
-            // tested
-            eigenvector_from_value( A, eig2, eig3, eigenvectors[0] );
-            eigenvector_from_value( A, eig1, eig3, eigenvectors[1] );
-            eigenvector_from_value( A, eig1, eig2, eigenvectors[2] );
-        }
-    }
-*/
-}
-
-/*
-template<typename T=float>
-inline void eigenvector_from_value( const T A[6],
-                                    const T& eig1, const T& eig2, T eigenvector[3] )
-{
-    const T& A11 = A[0];
-    const T& A12 = A[1];
-    const T& A13 = A[2];
-    const T& A22 = A[3];
-    const T& A23 = A[4];
-    const T& A33 = A[5];
-
-    T tempLength = 0, length = 0;
-    T tempVector[3];
-    T colum[3];
-    for( int i=0; i<3; i++ ) {
-        switch( i ) {
-        case 0:
-            colum[0] = A11 - eig2;
-            colum[1] = A12;
-            colum[2] = A13;
-            break;
-        case 1:
-            colum[0] = A12;
-            colum[1] = A22 - eig2;
-            colum[2] = A23;
-            break;
-        default:
-            colum[0] = A13;
-            colum[1] = A23;
-            colum[2] = A33 - eig2;
-            break;
-        }
-        tempVector[0] = colum[0] * (A11 - eig1) + colum[1] * A12 + colum[2] * A13;
-        tempVector[1] = colum[0] * A12 + colum[1] * (A22 - eig1) + colum[2] * A23;
-        tempVector[2] = colum[0] * A13 + colum[1] * A23 + colum[2] * (A33 - eig1);
-
-        tempLength = 0;
-        for( int k=0; k<3; k++ ) {
-            tempLength += tempVector[k] * tempVector[k];
-        }
-
-        // There are three columns in each resulting matrix of ( A-lambda_i * I ) * ( A-lambda_j * I )
-        // We choose the one with the maximum length for the sake of accuracy.
-        if( length < tempLength ) {
-            length = tempLength;
-            memcpy( eigenvector, tempVector, sizeof(T)*3);
-        }
-
-        if( length > BigEpsilon ) break;
-    }
-
-    // The vector is almost zero,
-//     assert( length >= SmallEpsilon && "All eigenvector are zero. " );
-
-    // TODO: for debuging
-//     if( length < SmallEpsilon ) {
-//         std::cerr << "Lenght of vector is too small. Maybe problematic. " << std::endl;
-//     }
-
-    // nromailized the vector
-    length = sqrt( length );
-    for( int k=0; k<3; k++ ) eigenvector[k] /= length;
-}
-*/
diff --git a/brick/processing/frangi_c/src/eigen.h b/brick/processing/frangi_c/src/eigen.h
deleted file mode 100644
index 1585f40..0000000
--- a/brick/processing/frangi_c/src/eigen.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Compute the eigen value decomposition of a 3 by 3 symetric matrix
-Input:
-A = [ A11  A12  A13     = [ A[0]  A[1]  A[2]
-A21  A22  A23          0    A[3]  A[4]
-A31  A32  A33 ];       0     0    A[5] ];
-Output:
-eigenvalues, eigenvectors
-
-Reference: http://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices
-*/
-// #include <cmath>
-// #include <assert.h>
-// #include <algorithm>
-// #include <iostream>
-
-
-
-
-// eigenvalue decomposition of a three by three symmetric matrix
-template<typename T=float>
-void eigen_decomp( const T A[6], T eigenvalues[3], T eigenvectors[3][3] );
-
-// give a 3 by 3 symmetric matrix and its eigenvalues, compute the corresponding eigenvectors
-template<typename T=float>
-inline void eigenvector_from_value( const T A[6], const T& eig1, const T& eig2, T eigenvector[3] );
-
-// normalize a vector
-template<typename T=float>
-inline void normalize( T v[3] );
-
-// compute the cross product of two vectors
-template<typename T=float>
-inline void cross_product( const T v1[3], const T v2[3], T v3[3] );
-
-// given a vector v1, compute two arbitrary normal vectors v2 and v3
-template<typename T=float>
-void normal_vectors(  const T v1[3], T v2[3], T v3[3] ) ;
diff --git a/brick/processing/frangi_c/src/kernel3D.cpp b/brick/processing/frangi_c/src/kernel3D.cpp
deleted file mode 100644
index 61c440f..0000000
--- a/brick/processing/frangi_c/src/kernel3D.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-#include "kernel3D.h"
-#include <opencv2/imgproc/imgproc.hpp>
-
-
-template<typename T>
-Kernel3D<T>::Kernel3D( const cv::Vec3i& n_size )
-{
-    reset( n_size );
-}
-
-
-template<typename T>
-void Kernel3D<T>::reset( const cv::Vec3i& n_size )
-{
-    Data3D<T>::reset( n_size, 0 );
-
-    for( int i=0; i<3; i++ )
-    {
-        center[i] = n_size[i]/2;
-        min_p[i] = -center[i];
-        max_p[i] = ( n_size[i]%2!=0 ) ? ( center[i]+1 ) : ( center[i] );
-    }
-}
-
-
-template <typename U>
-std::ostream& operator<<(std::ostream& out, const Kernel3D<U>& data)
-{
-    // diable output if the size is too big
-    for( int i=0; i<3; i++ )
-    {
-        if ( data.get_size(i)>9 )
-        {
-            std::cout << "I am so sorry. data size is too big to display." << std::endl;
-            return out;
-        }
-    }
-    // output data
-    int x, y, z;
-    for ( z=0; z<data.get_size(2); z++ )
-    {
-        out << "Level " << z << std::endl;
-        for ( y=0; y<data.get_size(1); y++ )
-        {
-            std::cout << "\t";
-            for( x=0; x<data.get_size(0); x++ )
-            {
-                out.precision(3);
-                out << std::scientific << data.at( x, y, z ) << " ";
-            }
-            out << std::endl;
-        }
-    }
-    return out;
-}
-
-
-
-template<typename T>
-Kernel3D<T> Kernel3D<T>::GaussianFilter3D( cv::Vec3i size )
-{
-    smart_assert( typeid(T)==typeid(float) || typeid(T)==typeid(double),
-                  "Can only use float or double" );
-
-    for( int i=0; i<3; i++ )
-        smart_assert( size[i]>0 && size[i]%2!=0, "size should be possitive odd number" );
-
-    // Calculate sigma from size:
-    //         sigma = 0.3 * ( (ksize-1)/2 - 1 ) + 0.8 = 0.15*ksize + 0.35
-    // reference: OpenCv Documentation 2.6.4.0 getGaussianKernel
-    // http://docs.opencv.org/modules/imgproc/doc/filtering.html#creategaussianfilter
-    // If we calculate sigma based on 99.7% Rule:
-    //         sigma = ( size - 1 ) /6 = 0.17 * size - 0.17
-    // But we are flowing the definition of OpenCv here
-    cv::Mat gaussian[3];
-    for( int i=0; i<3; i++ ) gaussian[i] = cv::getGaussianKernel( size[i], 0, CV_64F );
-
-    Kernel3D<T> kernel(size);
-    int x, y, z;
-    for( z=0; z<kernel.get_size_z(); z++ )
-    {
-        for( y=0; y<kernel.get_size_y(); y++ )
-        {
-            for( x=0; x<kernel.get_size_x(); x++ )
-            {
-                kernel.at(x,y,z)
-                    = gaussian[0].at<double>(x)
-                      * gaussian[1].at<double>(y)
-                      * gaussian[2].at<double>(z);
-            }
-        }
-    }
-
-    return kernel;
-}
-
diff --git a/brick/processing/frangi_c/src/kernel3D.h b/brick/processing/frangi_c/src/kernel3D.h
deleted file mode 100644
index be82fb6..0000000
--- a/brick/processing/frangi_c/src/kernel3D.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "data3D.h"
-#include <opencv2/imgproc/imgproc.hpp>
-
-// template<typename T> class Data3D;
-
-template<typename T = float>
-class Kernel3D : public Data3D<T>
-{
-    // operator overload
-    template <typename U>
-    friend std::ostream& operator<<(std::ostream& out, const Kernel3D<U>& data);
-
-public:
-    // constructor and destructors
-    Kernel3D() {};
-    Kernel3D( const cv::Vec3i& n_size );
-    virtual ~Kernel3D() {}
-    // getters
-    const int& min_pos(int i) const
-    {
-        return min_p[i];
-    }
-    const int& max_pos(int i) const
-    {
-        return max_p[i];
-    }
-    virtual const inline T& offset_at(const int& x, const int& y, const int& z) const
-    {
-        return Data3D<T>::at(x+center[0], y+center[1], z+center[2]);
-    }
-    virtual inline T& offset_at(const int& x, const int& y, const int& z)
-    {
-        return Data3D<T>::at(x+center[0], y+center[1], z+center[2]);
-    }
-
-    // setters
-    void reset( const cv::Vec3i& n_size );
-private:
-    // minimun and maximum possition
-    cv::Vec3i min_p, max_p, center;
-public:
-    // Some Global Functions for Getting 3D Kernel's that are commonly used.
-    static Kernel3D<T> GaussianFilter3D( cv::Vec3i size );
-    inline static Kernel3D<T> GaussianFilter3D( int ksize )
-    {
-        smart_assert( typeid(T)==typeid(float) || typeid(T)==typeid(double),
-                      "Can only use float or double" );
-        return GaussianFilter3D( cv::Vec3i(ksize, ksize, ksize) );
-    }
-    inline static Kernel3D<T> dx()
-    {
-        smart_assert( typeid(T)==typeid(float) || typeid(T)==typeid(double),
-                      "Can only use float or double" );
-        Kernel3D<T> dx( cv::Vec3i(3,1,1) );
-        dx.at( 0, 0, 0 ) = -0.5;
-        dx.at( 2, 0, 0 ) =  0.5;
-        return dx;
-    }
-    inline static Kernel3D<T> dy()
-    {
-        smart_assert( typeid(T)==typeid(float) || typeid(T)==typeid(double),
-                      "Can only use float or double" );
-        Kernel3D<T> dy( cv::Vec3i(1,3,1) );
-        dy.at( 0, 0, 0 ) = -0.5;
-        dy.at( 0, 2, 0 ) =  0.5;
-        return dy;
-    }
-    inline static Kernel3D<T> dz()
-    {
-        smart_assert( typeid(T)==typeid(float) || typeid(T)==typeid(double),
-                      "Can only use float or double" );
-        Kernel3D<T> dz( cv::Vec3i(1,1,3) );
-        dz.at( 0, 0, 0 ) = -0.5;
-        dz.at( 0, 0, 2 ) =  0.5;
-        return dz;
-    }
-
-};
diff --git a/brick/processing/frangi_c/src/main.cpp b/brick/processing/frangi_c/src/main.cpp
deleted file mode 100644
index 2158409..0000000
--- a/brick/processing/frangi_c/src/main.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#include <iostream>
-#include "detector.h"
-#include "data3D.h"
-#include "processing.h"
-
-using namespace std;
-using namespace cv;
-
-extern "C" {
-void vesselness(
-    float* array, const int width, const int height, const int depth,
-    float* response,
-    float sigma_from = 1.0f,
-    float sigma_to   = 8.10f,
-    float sigma_step = 0.3f,
-    float alpha = 1.0e-1f,
-    float beta  = 5.0e0f,
-    float gamma = 3.5e5f )
-{
-    // Sigma: Parameters for Vesselness
-    // [sigma_from, sigma_to]: the potential size rang of the vessels
-    // sigma_step: precision of computation
-    // Parameters for vesselness, please refer to Frangi's paper
-    // or this [blog](http://yzhong.co/?p=351)
-
-    Data3D<float> im_short(width, height, depth);
-    im_short.SetFromArray(array);
-
-    Data3D<Vesselness_Sig> vn_sig;
-    VesselDetector::compute_vesselness( im_short, vn_sig, sigma_from, sigma_to, sigma_step,
-                                        alpha, beta, gamma );
-
-//     Data3D<Vesselness_Sig> vn_sig_nms;
-//     IP::non_max_suppress( vn_sig, vn_sig_nms );
-//
-//     Data3D<Vesselness_Sig> vn_sig_et;
-//     IP::edge_tracing( vn_sig_nms, vn_sig_et, 0.45f, 0.05f );
-
-    int x,y,z;
-    float* array_cursor = response;
-    for( z=0; z<vn_sig.get_size_z(); z++ ) {
-        for( y=0; y<vn_sig.get_size_y(); y++ ) {
-            for( x=0; x<vn_sig.get_size_x(); x++ ) {
-                *array_cursor = vn_sig.at(x,y,z).rsp;
-                array_cursor++;
-            }
-        }
-    }
-//     vn_sig_et.CopyToArray(array);
-//     for (int idx=0; idx < 20; idx++) {
-//         cout << array[idx] << endl;
-//     }
-}
-}
-
-int main(void)
-{
-    float* array = new float[100*100*100];
-    float* response = new float[100*100*100];
-
-    vesselness( array, 100,100,100, response );
-
-    return 0;
-}
diff --git a/brick/processing/frangi_c/src/processing.cpp b/brick/processing/frangi_c/src/processing.cpp
deleted file mode 100644
index 984d645..0000000
--- a/brick/processing/frangi_c/src/processing.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-#include <opencv2/core/core.hpp>
-#include <queue>
-#include <iostream>
-#include "types.h"
-
-#include "processing.h"
-#include "processing_code.h"
-
-using namespace cv;
-using namespace std;
-
-void ImageProcessing::non_max_suppress( const Data3D<Vesselness_Sig>& src, Data3D<Vesselness_Sig>& dst )
-{
-    dst.reset( src.get_size() );
-
-    static const float s2 = sqrt(1/2.0f);
-    static const float s3 = sqrt(1/3.0f);
-
-    // 13 major orientations in 3d
-    static const int MAJOR_DIR_NUM = 13;
-    static const Vec3f major_dirs[MAJOR_DIR_NUM] = {
-        // directions along the axis, there are 3 of them
-        Vec3f(1, 0, 0), Vec3f(0, 1, 0), Vec3f(0, 0, 1),
-        // directions that lie within the 3D plane of two axis, there are 6 of them
-        Vec3f(s2, s2,0), Vec3f(0,s2, s2), Vec3f(s2,0, s2),
-        Vec3f(s2,-s2,0), Vec3f(0,s2,-s2), Vec3f(s2,0,-s2),
-        // directions that are equally in between three axis, there are 4 of them
-        Vec3f(s3,s3,s3), Vec3f(s3,s3,-s3), Vec3f(s3,-s3,s3), Vec3f(s3,-s3,-s3)
-    };
-
-    // there are 26 directions in 3D
-    static const int NUM_DIR_3D = 26;
-    Vec3i neighbor3d[NUM_DIR_3D] = {
-        // directions along the axis, there are 6 of them
-        Vec3i(0,0, 1), Vec3i(0, 1,0),  Vec3i( 1,0,0),
-        Vec3i(0,0,-1), Vec3i(0,-1,0),  Vec3i(-1,0,0),
-        // directions that lie within the 3D plane of two axis, there are 12 of them
-        Vec3i(0,1,1), Vec3i(0, 1,-1), Vec3i( 0,-1,1), Vec3i( 0,-1,-1),
-        Vec3i(1,0,1), Vec3i(1, 0,-1), Vec3i(-1, 0,1), Vec3i(-1, 0,-1),
-        Vec3i(1,1,0), Vec3i(1,-1, 0), Vec3i(-1, 1,0), Vec3i(-1,-1, 0),
-        // directions that are equally in between three axis, there are 8 of them
-        Vec3i( 1,1,1), Vec3i( 1,1,-1), Vec3i( 1,-1,1), Vec3i( 1,-1,-1),
-        Vec3i(-1,1,1), Vec3i(-1,1,-1), Vec3i(-1,-1,1), Vec3i(-1,-1,-1),
-    };
-
-    // cross section for the major orientation
-    vector<Vec3i> cross_section[MAJOR_DIR_NUM];
-
-    // Setting offsets that are perpendicular to dirs
-    for( int i=0; i<MAJOR_DIR_NUM; i++ ) {
-        for( int j=0; j<NUM_DIR_3D; j++ ) {
-            // multiply the two directions
-            float temp = major_dirs[i].dot( neighbor3d[j] );
-            // the temp is 0, store this direciton
-            if( abs(temp)<1.0e-5 ) {
-                cross_section[i].push_back( neighbor3d[j] );
-            }
-        }
-    }
-
-    int x,y,z;
-    for( z=0; z<src.get_size_z(); z++ ) {
-        for( y=0; y<src.get_size_y(); y++ ) {
-            for( x=0; x<src.get_size_x(); x++ ) {
-                // non-maximum surpression
-                bool isMaximum = true;
-
-                // Method I:
-                // find the major orientation
-                // assigning the orientation to one of the 13 categories
-                const Vec3f& cur_dir = src.at(x,y,z).dir;
-                int mdi = 0; // major direction id
-                float max_dot_product = 0;
-                for( int di=0; di<MAJOR_DIR_NUM; di++ ) {
-                    float current_dot_product = abs( cur_dir.dot(major_dirs[di]) );
-                    if( max_dot_product < current_dot_product ) {
-                        max_dot_product = current_dot_product;
-                        mdi = di;// update the major direction id
-                    }
-                }
-                for( unsigned int i=0; i<cross_section[mdi].size(); i++ ) {
-                    int ox = x + cross_section[mdi][i][0];
-                    int oy = y + cross_section[mdi][i][1];
-                    int oz = z + cross_section[mdi][i][2];
-                    if( src.isValid(ox,oy,oz) && src.at(x,y,z).rsp < src.at(ox,oy,oz).rsp ) {
-                        isMaximum = false;
-                        break;
-                    }
-                }
-
-                // Method II: Based on Sigma
-                //int sigma = (int) ceil( src.at(x,y,z).sigma );
-                //for( int i = -sigma; i <= sigma; i++ ) for( int j = -sigma; j <= sigma; j++ ) {
-                //	Vec3i offset = src.at(x,y,z).normals[0] * i + src.at(x,y,z).normals[1] * j;
-                //	int ox = x + offset[0];
-                //	int oy = y + offset[1];
-                //	int oz = z + offset[2];
-                //	if( src.isValid(ox,oy,oz) && src.at(x,y,z).rsp < src.at(ox,oy,oz).rsp ) {
-                //		isMaximum = false; break;
-                //	}
-                //}
-
-                if( isMaximum ) {
-                    dst.at(x,y,z) = src.at(x,y,z);
-                }
-            }
-        }
-    }
-}
-
-
-void ImageProcessing::edge_tracing( Data3D<Vesselness_Sig>& src, Data3D<Vesselness_Sig>& dst, const float& thres1, const float& thres2 )
-{
-    Data3D<float> src1d;
-    src.copyDimTo( src1d, 0 );
-    IP::normalize( src1d, 1.0f );
-
-    int x, y, z;
-    std::queue<Vec3i> q;
-    Data3D<unsigned char> mask( src.get_size() );
-    for(z=0; z<src.SZ(); z++) for (y=0; y<src.SY(); y++) for(x=0; x<src.SX(); x++) {
-                if( src1d.at(x,y,z) > thres1 ) {
-                    q.push( Vec3i(x,y,z) );
-                    mask.at(x,y,z) = 255;
-                }
-            }
-
-    Vec3i dir[26];
-    for( int i=0; i<26; i++ ) {
-        int index = (i + 14) % 27;
-        dir[i][0] = index/9%3 - 1;
-        dir[i][1] = index/3%3 - 1;
-        dir[i][2] = index/1%3 - 1;
-    }
-
-    while( !q.empty() ) {
-        Vec3i pos = q.front();
-        q.pop();
-        Vec3i off_pos;
-        for( int i=0; i<26; i++ ) {
-            off_pos = pos + dir[i];
-            if( src.isValid(off_pos) && !mask.at( off_pos ) && src1d.at(off_pos) > thres2 ) {
-                mask.at( off_pos ) = 255;
-                q.push( off_pos );
-            }
-        }
-    }
-
-    dst.reset( src.get_size() );
-    for(z=0; z<src.SZ(); z++) for (y=0; y<src.SY(); y++) for(x=0; x<src.SX(); x++) {
-                if( mask.at( x,y,z ) ) {
-                    dst.at( x,y,z ) = src.at( x,y,z );
-                    // dst.at( x,y,z ).rsp = sqrt( src1d.at( x,y,z ) );
-                }
-            }
-}
diff --git a/brick/processing/frangi_c/src/processing.h b/brick/processing/frangi_c/src/processing.h
deleted file mode 100644
index ae73611..0000000
--- a/brick/processing/frangi_c/src/processing.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "data3D.h"
-
-
-namespace ImageProcessing {
-
-void non_max_suppress( const Data3D<Vesselness_Sig>& src, Data3D<Vesselness_Sig>& dst );
-
-void edge_tracing( Data3D<Vesselness_Sig>& src, Data3D<Vesselness_Sig>& dst, const float& thres1, const float& thres2 );
-
-void dir_tracing( Data3D<Vesselness_All>& src_vn, Data3D<Vesselness_Sig>& dst );
-
-void edge_tracing_mst( Data3D<Vesselness_All>& src_vn, Data3D<Vesselness_Sig>& dst, const float& thres1, const float& thres2  );
-
-}
diff --git a/brick/processing/frangi_c/src/processing_code.h b/brick/processing/frangi_c/src/processing_code.h
deleted file mode 100644
index 6221073..0000000
--- a/brick/processing/frangi_c/src/processing_code.h
+++ /dev/null
@@ -1,121 +0,0 @@
-#pragma once
-
-#include <vector>
-#include "data3D.h"
-#include "kernel3D.h"
-#include "smart_assert.h"
-
-
-class Vesselness;
-class Vesselness_Sig;
-class Vesselness_Nor;
-class Vesselness_All;
-
-namespace ImageProcessing {
-template<typename T1, typename T2>
-bool GaussianBlur3D( const Data3D<T1>& src, Data3D<T2>& dst, int ksize, double sigma = 0.0 );
-
-template<typename T>
-void normalize( Data3D<T>& data, T norm_max = 1);
-
-
-///////////////////////////////////////////////////////////////////////////
-// NON-MAXIMUM SUPPRESSION
-void non_max_suppress( const Data3D<Vesselness_Sig>& src, Data3D<Vesselness_Sig>& dst );
-void edge_tracing( Data3D<Vesselness_Sig>& src, Data3D<Vesselness_Sig>& dst, const float& thres1 = 0.85f, const float& thres2 = 0.10f );
-void dir_tracing( Data3D<Vesselness_All>& src, Data3D<Vesselness_Sig>& res_dt );
-void edge_tracing_mst( Data3D<Vesselness_All>& src, Data3D<Vesselness_Sig>& dst, const float& thres1 = 0.85f, const float& thres2 = 0.10f );
-}
-
-namespace IP = ImageProcessing;
-
-
-
-template<typename T1, typename T2>
-bool ImageProcessing::GaussianBlur3D( const Data3D<T1>& src, Data3D<T2>& dst, int ksize, double sigma )
-{
-    smart_return( ksize%2!=0, "kernel size should be odd number", false );
-
-    //////////////////////////////////////////////////////////////////////////////////////
-    // Relationship between Sigma and Kernal Size (ksize)
-    /////////////////////////////
-    // Option I - Based on OpenCV
-    //   Calculate sigma from size:
-    //         sigma = 0.3 * ( (ksize-1)/2 - 1 ) + 0.8 = 0.15*ksize + 0.35
-    //   Calculate size from sigma:
-    //         ksize = ( sigma - 0.35 ) / 0.15 = 6.67 * sigma - 2.33
-    //   Reference: OpenCv Documentation 2.6.4.0 getGaussianKernel
-    //     http://docs.opencv.org/modules/imgproc/doc/filtering.html#creategaussianfilter
-    // Option II - Based on the traditional 99.7%
-    //   Calculate size from sigma:
-    //         ksize = 6 * sigma + 1
-    //   Calculate sigma from ksize:
-    //         sigma = (size - 1)/6 = 0.17 * size - 0.17
-
-    cv::Mat gk = cv::getGaussianKernel( ksize, sigma, CV_64F );
-
-    int hsize = ksize/2;
-    smart_assert( 2*hsize+1==ksize, "Alert: Bug!" );
-
-    cv::Vec3i spos, epos;
-    spos = cv::Vec3i(0, 0, 0);
-    epos = src.get_size();
-
-    // gaussian on x-direction
-    Data3D<T2> tmp1( src.get_size(), T2(0) ); // the data will be set to zero
-    #pragma omp parallel for
-    for( int z=spos[2]; z<epos[2]; z++ ) for( int y=spos[1]; y<epos[1]; y++ ) for( int x=spos[0]; x<epos[0]; x++ ) {
-                double sum = 0.0;
-                for( int i=0; i<ksize; i++) {
-                    int x2 = x+i-hsize;
-                    if( x2>=0 && x2<epos[0] ) {
-                        tmp1.at(x, y, z) = T2( gk.at<double>(i) * src.at(x2, y, z) + tmp1.at(x, y, z));
-                        sum += gk.at<double>(i);
-                    }
-                }
-                tmp1.at(x, y, z) = T2( tmp1.at(x, y, z)/sum );
-            }
-
-
-    // gaussian on y-direction
-    Data3D<T2> tmp2( src.get_size(), T2(0) ); // the data will be set to zero
-    #pragma omp parallel for
-    for( int z=spos[2]; z<epos[2]; z++ ) for( int y=spos[1]; y<epos[1]; y++ ) for( int x=spos[0]; x<epos[0]; x++ ) {
-                double sum = 0.0;
-                for( int i=0; i<ksize; i++) {
-                    int y2 = y+i-hsize;
-                    if( y2>=0 && y2<epos[1] ) {
-                        tmp2.at(x, y, z) = T2( gk.at<double>(i) * tmp1.at(x, y2, z) + tmp2.at(x, y, z));
-                        sum += gk.at<double>(i);
-                    }
-                }
-                tmp2.at(x, y, z) = T2( tmp2.at(x, y, z)/sum );
-            }
-
-    tmp1.reset(); // tmp1 is no long in use. release memory
-
-    // gaussian on z-direction
-    dst.reset( src.get_size() );
-    #pragma omp parallel for
-    for( int z=spos[2]; z<epos[2]; z++ ) for( int y=spos[1]; y<epos[1]; y++ ) for( int x=spos[0]; x<epos[0]; x++ ) {
-                double sum = 0.0;
-                for( int i=0; i<ksize; i++) {
-                    int z2 = z+i-hsize;
-                    if( z2>=0 && z2<epos[2] ) {
-                        dst.at(x, y, z) = T2( dst.at(x, y, z) + gk.at<double>(i) * tmp2.at(x, y, z2) );
-                        sum += gk.at<double>(i);
-                    }
-                }
-                dst.at(x, y, z) = T2( dst.at(x, y, z)/sum );
-            }
-
-    return true;
-}
-
-
-template<typename T>
-void ImageProcessing::normalize( Data3D<T>& data, T norm_max )
-{
-    cv::Vec<T, 2> min_max = data.get_min_max_value();
-    data.getMat() = 1.0 * norm_max / (min_max[1]-min_max[0]) * (data.getMat() - min_max[0]);
-}
diff --git a/brick/processing/frangi_c/src/smart_assert.h b/brick/processing/frangi_c/src/smart_assert.h
deleted file mode 100644
index a6d38fd..0000000
--- a/brick/processing/frangi_c/src/smart_assert.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Smart Assertion
- *  - Show assertion under debug mode
- *  - Print assertion message udner release mode
- *
- * Created by Yuchen on Apr 30th, 2013
- * Last Modified by Yuchen on Jul 2nd, 2013
- *
- * Example:
-	Code:
-		int i = -1;
-		smart_assert(i>=0 && i<3, "Index out of bound" );
-	Output:
-		Assertion failed: i>0 && i<3
-		  Messages: Index out of bound
-		  Location: file main.cpp, line 17
- */
-#ifndef SMART_ASSERT_H
-#define SMART_ASSERT_H
-#include <assert.h>
-#include <iostream>
-
-// The following color is defined using [ANSI colour codes](http://en.wikipedia.org/wiki/ANSI_escape_code)
-#define SMA_RED   "\033[0;31m"
-#define SMA_BLACK "\x1b[0;49m"
-
-#define smart_assert( condition, message ) \
-	if( !(condition) ) { \
-		std::cerr << std::endl; \
-		std::cerr << SMA_RED << "Assertion failed: " << (#condition) << std::endl; \
-		std::cerr << "  Messages: " << message << std::endl; \
-		std::cerr << "  Location: file "<< __FILE__ << ", line " << __LINE__ << std::endl; \
-		std::cerr << SMA_BLACK << std::endl;\
-	}
-
-#define smart_return( condition, message, return_value ) \
-    smart_assert( condition, message )\
-	if( !(condition) ) { \
-        return return_value;\
-	}
-
-#endif
diff --git a/brick/processing/frangi_c/src/type_info.h b/brick/processing/frangi_c/src/type_info.h
deleted file mode 100644
index b339e18..0000000
--- a/brick/processing/frangi_c/src/type_info.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#pragma once
-
-#include <string>
-#include <opencv2/core/core.hpp>
-
-template <class T> struct TypeInfo {
-    static std::string str()
-    {
-        return "undefined";
-    }
-    static int CV_TYPE()
-    {
-        return -1;
-    }
-};
-
-template <> struct TypeInfo <int> {
-    static std::string str()
-    {
-        return "int";
-    }
-    static int CV_TYPE()
-    {
-        return CV_32S;
-    }
-};
-
-template <> struct TypeInfo <short> {
-    static std::string str()
-    {
-        return "short";
-    }
-    static int CV_TYPE()
-    {
-        return CV_16S;
-    }
-};
-
-template <> struct TypeInfo <float> {
-    static std::string str()
-    {
-        return "float";
-    }
-    static int CV_TYPE()
-    {
-        return CV_32F;
-    }
-};
-
-template <> struct TypeInfo <double> {
-    static std::string str()
-    {
-        return "double";
-    }
-    static int CV_TYPE()
-    {
-        return CV_64F;
-    }
-};
-
-template <> struct TypeInfo <unsigned short> {
-    static std::string str()
-    {
-        return "ushort";
-    }
-    static int CV_TYPE()
-    {
-        return CV_16U;
-    }
-};
-
-template <> struct TypeInfo <unsigned char> {
-    static std::string str()
-    {
-        return "uchar";
-    }
-    static int CV_TYPE()
-    {
-        return CV_8U;
-    }
-};
diff --git a/brick/processing/frangi_c/src/types.h b/brick/processing/frangi_c/src/types.h
deleted file mode 100644
index 3b64784..0000000
--- a/brick/processing/frangi_c/src/types.h
+++ /dev/null
@@ -1,297 +0,0 @@
-#pragma once
-
-#include <opencv2/core/core.hpp>
-#include "type_info.h"
-#include "smart_assert.h"
-
-// VesselnessTypes.h
-// Define 4 different vesselness data types
-// 1) class Vesselness
-//		vesselness response (rsp) + vessel orientation (dir)
-// 2) class Vesselness_Sig
-//		vesselness response (rsp) + vessel orientation (dir) + vessel size (sigma)
-// 3) class Vesselness_Nor
-//		vesselness response (rsp) + vessel orientation (dir) + vessel orientations normals (normals)
-// 4) class Vesselness_All
-//		vesselness response (rsp) + vessel orientation (dir) + vessel orientations normals (normals)
-
-struct Vesselness_Data;
-struct Vesselness_Sig_Data;
-struct Vesselness_Nor_Data;
-struct Vesselness_All_Data;
-
-class Vesselness;
-class Vesselness_Sig;
-class Vesselness_Nor;
-class Vesselness_All;
-
-struct Vesselness_Data {
-    float rsp;			// vesselness response
-    cv::Vec3f dir;			// vessel dirction
-
-    Vesselness_Data( float s = 0.0f ) : rsp( s ), dir( cv::Vec3f(1,0,0) ) { }
-    bool operator>( const Vesselness_Data& right ) const
-    {
-        return ( (this->rsp) > right.rsp );
-    }
-    bool operator<( const Vesselness_Data& right ) const
-    {
-        return ( (this->rsp) < right.rsp );
-    }
-};
-
-struct Vesselness_Sig_Data : public Vesselness_Data {
-    float sigma;		// relative size of the vessel
-
-    Vesselness_Sig_Data( float s = 0.0f ) : Vesselness_Data ( s ) { }
-};
-
-struct Vesselness_Nor_Data : public Vesselness_Data {
-    cv::Vec3f normals[2];	// normals of vessel orientation
-};
-
-struct Vesselness_All_Data : public Vesselness_Data {
-    float sigma;		// relative size of the vessel
-    cv::Vec3f normals[2];	// normals of vessel orientation
-};
-
-
-
-
-
-class Vesselness : public Vesselness_Data {
-public:
-    Vesselness( const float& val = 0 ) : Vesselness_Data( val ) { }
-
-    // Size tells us how much number of float we are using in the structure.
-    // The returned value should be:
-    //  4 for Vesselness;
-    //  5 for Vesselness_Sig;
-    // 10 for Vesselness_Nor;
-    // 11 for Vesselness_All;
-    // This virtual function here will take 2*4 = 8 bytes of data
-    static const int _size = sizeof(Vesselness_Data)/sizeof(float);
-    int size(void) const
-    {
-        return _size;
-    }
-
-    const float& operator[]( const int& i ) const
-    {
-        smart_return( i>=0&&i<_size, "index invalid", *(float*)(this) );
-        return *((float*)(this)+i);
-    }
-
-    float& operator[]( const int& i )
-    {
-        smart_return( i>=0&&i<_size, "index invalid", *(float*)(this) );
-        return *((float*)(this)+i);
-    }
-};
-
-
-class Vesselness_Nor : public Vesselness_Nor_Data {
-public:
-    static const int _size = sizeof(Vesselness_Nor_Data)/sizeof(float);
-
-    const float& operator[]( const int& i ) const
-    {
-        smart_return( i>=0&&i<_size, "index invalid", *(float*)(this) );
-        return *((float*)(this)+i);
-    }
-
-    float& operator[]( const int& i )
-    {
-        smart_return( i>=0&&i<_size, "index invalid", *(float*)(this) );
-        return *((float*)(this)+i);
-    }
-};
-
-class Vesselness_All : public Vesselness_All_Data {
-public:
-    static const int _size = sizeof(Vesselness_All_Data)/sizeof(float);
-
-    Vesselness_All() {}
-
-    Vesselness_All( const Vesselness_Nor& v_Nor, const float& s )
-    {
-        this->dir        = v_Nor.dir;
-        this->normals[0] = v_Nor.normals[0];
-        this->normals[1] = v_Nor.normals[1];
-        this->rsp        = v_Nor.rsp;
-        this->sigma      = s;
-    }
-
-    const float& operator[]( const int& i ) const
-    {
-        smart_return( i>=0&&i<_size, "index invalid", *(float*)(this) );
-        return *((float*)(this)+i);
-    }
-
-    float& operator[]( const int& i )
-    {
-        smart_return( i>=0&&i<_size, "index invalid", *(float*)(this) );
-        return *((float*)(this)+i);
-    }
-};
-
-
-class Vesselness_Sig : public Vesselness_Sig_Data {
-    Vesselness_Sig& operator=( const float& s );
-public:
-    static const int _size = sizeof(Vesselness_Sig_Data)/sizeof(float);
-
-    Vesselness_Sig() { }
-    Vesselness_Sig( float s ) : Vesselness_Sig_Data( s ) { }
-    operator Vesselness( )
-    {
-        Vesselness vn;
-        vn.rsp = this->rsp;
-        vn.dir = this->dir;
-        return vn;
-    }
-    operator float()
-    {
-        return this->rsp;
-    }
-
-    Vesselness_Sig( const Vesselness_All& src )
-    {
-        this->rsp   = src.rsp;
-        this->dir   = src.dir;
-        this->sigma = src.sigma;
-    }
-
-    Vesselness_Sig& operator=( const Vesselness_All& src )
-    {
-        this->rsp   = src.rsp;
-        this->dir   = src.dir;
-        this->sigma = src.sigma;
-        return (*this);
-    }
-
-    const float& operator[]( const int& i ) const
-    {
-        smart_return( i>=0&&i<_size, "index invalid", *(float*)(this) );
-        return *((float*)(this)+i);
-    }
-
-    float& operator[]( const int& i )
-    {
-        smart_return( i>=0&&i<_size, "index invalid", *(float*)(this) );
-        return *((float*)(this)+i);
-    }
-};
-
-// The namespace cv here is necessary.
-// Reference: http://stackoverflow.com/questions/2282349/specialization-of-templateclass-tp-struct-stdless-in-different-namespace
-namespace cv {
-template< > class DataType<     Vesselness     > : public DataType<     Vec<float, Vesselness::_size> > { };
-// template< > class DataDepth<    Vesselness     > : public DataDepth<    Vec<float, Vesselness::_size> > { };
-template< > class traits::Type< Vesselness     > : public traits::Type< Vec<float, Vesselness::_size> > { };
-
-template< > class DataType<     Vesselness_Sig > : public DataType<     Vec<float, Vesselness_Sig::_size> > { };
-// template< > class DataDepth<    Vesselness_Sig > : public DataDepth<    Vec<float, Vesselness_Sig::_size> > { };
-template< > class traits::Type< Vesselness_Sig > : public traits::Type< Vec<float, Vesselness_Sig::_size> > { };
-
-template< > class DataType<     Vesselness_Nor > : public DataType<     Vec<float, Vesselness_Nor::_size> > { };
-// template< > class DataDepth<    Vesselness_Nor > : public DataDepth<    Vec<float, Vesselness_Nor::_size> > { };
-template< > class traits::Type< Vesselness_Nor > : public traits::Type< Vec<float, Vesselness_Nor::_size> > { };
-
-template< > class DataType<     Vesselness_All > : public DataType<     Vec<float, Vesselness_All::_size> > { };
-// template< > class DataDepth<    Vesselness_All > : public DataDepth<    Vec<float, Vesselness_All::_size> > { };
-template< > class traits::Type< Vesselness_All > : public traits::Type< Vec<float, Vesselness_All::_size> > { };
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Reference: These following are defined in <core.hpp>
-//
-//template<> class DataType<int>
-//{
-//public:
-//    typedef int value_type;
-//    typedef value_type work_type;
-//    typedef value_type channel_type;
-//    typedef value_type vec_type;
-//    enum { generic_type = 0, depth = DataDepth<channel_type>::value, channels = 1,
-//           fmt=DataDepth<channel_type>::fmt,
-//           type = CV_MAKETYPE(depth, channels) };
-//};
-//
-//template<> class DataType<float>
-//{
-//public:
-//    typedef float value_type;
-//    typedef value_type work_type;
-//    typedef value_type channel_type;
-//    typedef value_type vec_type;
-//    enum { generic_type = 0, depth = DataDepth<channel_type>::value, channels = 1,
-//           fmt=DataDepth<channel_type>::fmt,
-//           type = CV_MAKETYPE(depth, channels) };
-//};
-//
-//template<typename _Tp, int cn> class DataType<Vec<_Tp, cn> >
-//{
-//public:
-//    typedef Vec<_Tp, cn> value_type;
-//    typedef Vec<typename DataType<_Tp>::work_type, cn> work_type;
-//    typedef _Tp channel_type;
-//    typedef value_type vec_type;
-//    enum { generic_type = 0, depth = DataDepth<channel_type>::value, channels = cn,
-//           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,
-//           type = CV_MAKETYPE(depth, channels) };
-//};
-
-
-template <> struct TypeInfo <Vesselness> {
-    static std::string str()
-    {
-        std::stringstream ss;
-        ss << "float," << Vesselness::_size;
-        return ss.str();
-    }
-    static int CV_TYPE()
-    {
-        return CV_32FC( Vesselness::_size );
-    }
-};
-
-template <> struct TypeInfo <Vesselness_Sig> {
-    static std::string str()
-    {
-        std::stringstream ss;
-        ss << "float," << Vesselness_Sig::_size;
-        return ss.str();
-    }
-    static int CV_TYPE()
-    {
-        return CV_32FC( Vesselness_Sig::_size );
-    }
-};
-
-template <> struct TypeInfo <Vesselness_Nor> {
-    static std::string str()
-    {
-        std::stringstream ss;
-        ss << "float," << Vesselness_Nor::_size;
-        return ss.str();
-    }
-    static int CV_TYPE()
-    {
-        return CV_32FC( Vesselness_Nor::_size );
-    }
-};
-
-template <> struct TypeInfo <Vesselness_All> {
-    static std::string str()
-    {
-        std::stringstream ss;
-        ss << "float," << Vesselness_All::_size;
-        return ss.str();
-    }
-    static int CV_TYPE()
-    {
-        return CV_32FC( Vesselness_All::_size );
-    }
-};
diff --git a/brick/processing/frangi_py/frangi_3d.pxd b/brick/processing/frangi_py/frangi_3d.pxd
deleted file mode 100644
index f5e1375..0000000
--- a/brick/processing/frangi_py/frangi_3d.pxd
+++ /dev/null
@@ -1,44 +0,0 @@
-cimport numpy as np_
-
-
-ctypedef np_.float64_t real_pix_v_t
-#ctypedef np_.ndarray[real_pix_v_t, ndim=3] real_img_t
-
-
-#cpdef tuple FrangiEnhancement(
-#    np_.ndarray[real_pix_v_t, ndim=2] img,
-#    tuple scale_range,
-#    double scale_step = *,
-#    double alpha = *,
-#    double beta = *,
-#    double frangi_c = *,
-#    bint bright_on_dark = *,
-#    bint in_parallel = *
-#)
-
-
-cdef np_.ndarray[real_pix_v_t, ndim=3] FrangiEnhancementOneScale(
-    np_.ndarray[real_pix_v_t, ndim=3] img,
-    double scale,
-    double alpha = *,
-    double beta = *,
-    double frangi_c = *,
-    bint bright_on_dark = *,
-    object shared_enhanced = *
-)
-
-
-#cdef tuple[np_.ndarray[real_pix_v_t, ndim=3],np_.ndarray[real_pix_v_t, ndim=3],np_.ndarray[real_pix_v_t, ndim=3],np_.ndarray[real_pix_v_t, ndim=3],np_.ndarray[real_pix_v_t, ndim=3],np_.ndarray[real_pix_v_t, ndim=3]] HessianMatrix(
-#    np_.ndarray[real_pix_v_t, ndim=3] img, double scale
-#)
-
-
-#cdef tuple[np_.ndarray[real_pix_v_t, ndim=3],np_.ndarray[real_pix_v_t, ndim=3],np_.ndarray[real_pix_v_t, ndim=3]] EigenValues(
-#    np_.ndarray[real_pix_v_t, ndim=3] Dxx, np_.ndarray[real_pix_v_t, ndim=3] Dxy, np_.ndarray[real_pix_v_t, ndim=3] Dxz, np_.ndarray[real_pix_v_t, ndim=3] Dyy, np_.ndarray[real_pix_v_t, ndim=3] Dyz, np_.ndarray[real_pix_v_t, ndim=3] Dzz
-#)
-
-
-cdef np_.ndarray[real_pix_v_t, ndim=3] SortedByAbsValues(np_.ndarray[real_pix_v_t, ndim=3] array, int axis = *)
-
-
-cdef np_.ndarray[real_pix_v_t, ndim=3] CarefullDivision(np_.ndarray[real_pix_v_t, ndim=3] array_1, np_.ndarray[real_pix_v_t, ndim=3] array_2)
diff --git a/brick/processing/frangi_py/frangi_3d.py b/brick/processing/frangi_py/frangi_3d.py
deleted file mode 100644
index 9fbff6b..0000000
--- a/brick/processing/frangi_py/frangi_3d.py
+++ /dev/null
@@ -1,292 +0,0 @@
-# Copyright CNRS/Inria/UNS
-# Contributor(s): Eric Debreuve (since 2019)
-#
-# eric.debreuve@cnrs.fr
-#
-# This software is governed by the CeCILL  license under French law and
-# abiding by the rules of distribution of free software.  You can  use,
-# modify and/ or redistribute the software under the terms of the CeCILL
-# license as circulated by CEA, CNRS and INRIA at the following URL
-# "http://www.cecill.info".
-#
-# As a counterpart to the access to the source code and  rights to copy,
-# modify and redistribute granted by the license, users are provided only
-# with a limited warranty  and the software's author,  the holder of the
-# economic rights,  and the successive licensors  have only  limited
-# liability.
-#
-# In this respect, the user's attention is drawn to the risks associated
-# with loading,  using,  modifying and/or developing or reproducing the
-# software by the user in light of its specific status of free software,
-# that may mean  that it is complicated to manipulate,  and  that  also
-# therefore means  that it is reserved for developers  and  experienced
-# professionals having in-depth computer knowledge. Users are therefore
-# encouraged to load and test the software's suitability as regards their
-# requirements in conditions enabling the security of their systems and/or
-# data to be ensured and,  more generally, to use and operate it in the
-# same conditions as regards security.
-#
-# The fact that you are presently reading this means that you have had
-# knowledge of the CeCILL license and that you accept its terms.
-
-'''
-Follows: https://github.com/ellisdg/frangi3d
-'''
-
-from brick.general.type import array_t
-
-import multiprocessing as pl_
-from ctypes import c_float as c_float_t
-from multiprocessing.sharedctypes import Array as shared_array_t
-from typing import Optional, Tuple
-
-import itk as ik_
-import numpy as np_
-from scipy import ndimage as im_
-
-
-_hessian_matrices = None
-
-
-def FrangiEnhancement(
-    img: array_t,
-    scale_range: Tuple[float, float],
-    scale_step: float = 2.0,
-    alpha: float = 0.5,
-    beta: float = 0.5,
-    frangi_c: float = 500.0,
-    bright_on_dark: bool = True,
-    in_parallel: bool = False,
-) -> Tuple[array_t, array_t]:
-    #
-    global _hessian_matrices
-
-    img = img.astype(np_.float32, copy=False)
-    scales = np_.linspace(
-        scale_range[0],
-        scale_range[1],
-        num=np_.ceil((scale_range[1] - scale_range[0]) / scale_step) + 1,
-    )
-
-    if in_parallel and (pl_.get_start_method(allow_none=False) == "fork"):
-        _hessian_matrices = None
-        FrangiEnhancement_fct = _FrangiEnhancementParallel
-    else:
-        _hessian_matrices = np_.empty((*img.shape, 3, 3), dtype=np_.float32)
-        FrangiEnhancement_fct = _FrangiEnhancementSequential
-
-    enhanced, scale_map = FrangiEnhancement_fct(
-        img,
-        scales,
-        alpha=alpha,
-        beta=beta,
-        frangi_c=frangi_c,
-        bright_on_dark=bright_on_dark,
-    )
-
-    _hessian_matrices = None
-
-    return enhanced, scale_map
-
-
-def _FrangiEnhancementSequential(
-    img: array_t,
-    scales: array_t,
-    alpha: float = 0.5,
-    beta: float = 0.5,
-    frangi_c: float = 500.0,
-    bright_on_dark: bool = True,
-) -> Tuple[array_t, array_t]:
-    #
-    enhanced = None
-    scale_map = None
-
-    for s_idx, scale in enumerate(scales):
-        local_enhanced = _FrangiEnhancementOneScale(
-            img,
-            scale,
-            alpha=alpha,
-            beta=beta,
-            frangi_c=frangi_c,
-            bright_on_dark=bright_on_dark,
-        )
-
-        if s_idx > 0:
-            larger_map = local_enhanced > enhanced
-            enhanced[larger_map] = local_enhanced[larger_map]
-            scale_map[larger_map] = scale
-        else:
-            enhanced = local_enhanced
-            scale_map = np_.full(img.shape, scale, dtype=np_.float32)
-
-    return enhanced, scale_map
-
-
-def _FrangiEnhancementParallel(
-    img: array_t,
-    scales: array_t,
-    alpha: float = 0.5,
-    beta: float = 0.5,
-    frangi_c: float = 500.0,
-    bright_on_dark: bool = True,
-) -> Tuple[array_t, array_t]:
-    #
-    fixed_args = {
-        "alpha": alpha,
-        "beta": beta,
-        "frangi_c": frangi_c,
-        "bright_on_dark": bright_on_dark,
-    }
-
-    shared_enhanced_s = tuple(shared_array_t(c_float_t, img.size) for ___ in scales)
-    processes = tuple(
-        pl_.Process(
-            target=_FrangiEnhancementOneScale,
-            args=(img, scale),
-            kwargs={**fixed_args, "shared_enhanced": shared_enhanced,},
-        )
-        for scale, shared_enhanced in zip(scales, shared_enhanced_s)
-    )
-
-    for process in processes:
-        process.start()
-    for process in processes:
-        process.join()
-
-    enhanced = np_.array(shared_enhanced_s[0])
-    scale_map = np_.full(img.size, scales[0], dtype=np_.float32)
-    for s_idx, shared_enhanced in enumerate(shared_enhanced_s[1:], start=1):
-        local_enhanced = np_.array(shared_enhanced)
-        larger_map = local_enhanced > enhanced
-        enhanced[larger_map] = local_enhanced[larger_map]
-        scale_map[larger_map] = scales[s_idx]
-
-    enhanced = enhanced.astype(np_.float32, copy=False).reshape(img.shape)
-    scale_map = scale_map.astype(np_.float32, copy=False).reshape(img.shape)
-
-    return enhanced, scale_map
-
-
-def _FrangiEnhancementOneScale(
-    img: array_t,
-    scale: float,
-    alpha: float = 0.5,
-    beta: float = 0.5,
-    frangi_c: float = 500.0,
-    bright_on_dark: bool = True,
-    shared_enhanced: shared_array_t = None,
-) -> Optional[array_t]:
-    #
-    print(f"    scale={scale}")
-
-    sorted_eigenvalues = _EigenValuesOfHessianMatrix(img, scale)
-
-    # Absolute plate, blob, and background maps
-    abs_eig_val = np_.fabs(sorted_eigenvalues)
-    plate_map = _CarefullDivision(abs_eig_val[...,1], abs_eig_val[...,2])
-    blob_map = _CarefullDivision(abs_eig_val[...,0], np_.sqrt(np_.prod(abs_eig_val[...,1:], axis = -1)))
-    bckgnd = np_.sqrt(np_.sum(abs_eig_val ** 2, axis = -1))
-
-    # Normalized plate, blob, and background maps
-    plate_factor = -2.0 * alpha ** 2
-    blob_factor = -2.0 * beta ** 2
-    bckgnd_factor = -2.0 * frangi_c ** 2
-    plate_map = 1.0 - np_.exp(plate_map ** 2 / plate_factor)
-    blob_map = np_.exp(blob_map ** 2 / blob_factor)
-    bckgnd = 1.0 - np_.exp(bckgnd ** 2 / bckgnd_factor)
-
-    local_enhanced = plate_map * blob_map * bckgnd
-    if bright_on_dark:
-        eig_condition = np_.any(sorted_eigenvalues[...,1:] > 0.0, axis=-1)
-    else:
-        eig_condition = np_.any(sorted_eigenvalues[...,1:] < 0.0, axis=-1)
-    invalid_condition = np_.logical_not(np_.isfinite(local_enhanced))
-    local_enhanced[np_.logical_or(eig_condition, invalid_condition)] = 0.0
-
-    if shared_enhanced is None:
-        return local_enhanced
-    else:
-        shared_enhanced[:] = local_enhanced.flatten()[:]
-
-
-def _ITKFrangiEnhancementOneScale(
-    img: array_t,
-    scale: float,
-    alpha: float = 0.5,
-    beta: float = 0.5,
-    frangi_c: float = 500.0,
-    bright_on_dark: bool = True,
-    shared_enhanced: shared_array_t = None,
-) -> Optional[array_t]:
-    '''
-    Do not produce nice resultas as is. Parameter tuning?
-    '''
-    print(f"    scale={scale}")
-
-    assert bright_on_dark
-
-    img = ik_.image_view_from_array(img)
-    hessian_image = ik_.hessian_recursive_gaussian_image_filter(img, sigma=scale)
-
-    vesselness_filter = ik_.Hessian3DToVesselnessMeasureImageFilter[ik_.ctype('float')].New()
-    vesselness_filter.SetInput(hessian_image)
-    # vesselness_filter.SetAlpha1(args.alpha1)
-    # vesselness_filter.SetAlpha2(args.alpha2)
-
-    # Do not view-version here since vesselness_filter is local
-    local_enhanced = ik_.array_from_image(vesselness_filter)
-
-    if shared_enhanced is None:
-        return local_enhanced
-    else:
-        shared_enhanced[:] = local_enhanced.flatten()[:]
-
-
-def _EigenValuesOfHessianMatrix(img: array_t, scale: float) -> array_t:
-    #
-    global _hessian_matrices
-
-    if scale > 0.0:
-        img = scale ** 2 * im_.gaussian_filter(img, scale)
-    else:
-        img = scale ** 2 * img
-
-    if _hessian_matrices is None:
-        hessian_matrices = np_.empty((*img.shape, 3, 3), dtype=np_.float32)
-    else:
-        hessian_matrices = _hessian_matrices
-    Dx, Dy, Dz = np_.gradient(img)
-    (
-        hessian_matrices[..., 0, 0],
-        hessian_matrices[..., 0, 1],
-        hessian_matrices[..., 0, 2],
-    ) = np_.gradient(Dx)
-    hessian_matrices[..., 1, 1], hessian_matrices[..., 1, 2] = np_.gradient(
-        Dy, axis=(1, 2)
-    )
-    hessian_matrices[..., 2, 2] = np_.gradient(Dz, axis=2)
-
-    hessian_matrices[..., 1, 0] = hessian_matrices[..., 0, 1]
-    hessian_matrices[..., 2, 0] = hessian_matrices[..., 0, 2]
-    hessian_matrices[..., 2, 1] = hessian_matrices[..., 1, 2]
-
-    eigenvalues = np_.linalg.eigvalsh(hessian_matrices)
-
-    # Sorted by abs value
-    index = list(np_.ix_(*[np_.arange(size) for size in eigenvalues.shape]))
-    index[-1] = np_.fabs(eigenvalues).argsort(axis=-1)
-    sorted_eigenvalues = eigenvalues[tuple(index)]
-
-    return sorted_eigenvalues
-
-
-def _CarefullDivision(array_1: array_t, array_2: array_t) -> array_t:
-    #
-    null_map = array_2 == 0.0
-    if null_map.any():
-        denominator = array_2.copy()
-        denominator[null_map] = 1.0e-10
-    else:
-        denominator = array_2
-
-    return array_1 / denominator
diff --git a/nutrimorph.py b/nutrimorph.py
index 41fdf35..e0d1031 100644
--- a/nutrimorph.py
+++ b/nutrimorph.py
@@ -39,6 +39,7 @@
 
 import brick.component.connection as cn_
 import brick.component.extension as xt_
+import brick.component.glial_cmp as gl_
 import brick.component.soma as sm_
 import brick.general.feedback as fb_
 # from main_prm import *
@@ -87,13 +88,20 @@ start_time = tm_.time()
 
 # --- Images
 image = io_.imread(data_path)
-assert image.shape.__len__() == 3
-image = image[:, 512:, 512:]
+assert image.ndim == 3
+image = image[:, 512:, 512:]#562
 img_shape = image.shape
+#
+# max_img = image.max()
+# image.fill(image.min())
+# image[2:3,10:11,:] = max_img
+#
+print(f"IMAGE: s.{img_shape} t.{image.dtype} m.{image.min()} M.{image.max()}")
 
-image_for_soma = sm_.NormalizedImage(image)
-image_for_ext = xt_.NormalizedImage(image)
+image_for_soma = gl_.NormalizedImage(image)
+image_for_ext = gl_.NormalizedImage(image)
 costs = 1.0 / (image + 1.0)
+print(f"NRM-IMG: t.{image_for_soma.dtype} m.{image_for_soma.min():.2f} M.{image_for_soma.max():.2f}")
 
 
 # --- Initialization
-- 
GitLab