diff --git a/bob/bio/vein/algorithms/HammingDistance.py b/bob/bio/vein/algorithms/HammingDistance.py
index 391803d54ca9fb0cdf59fd84afde8035be7dcc50..cb7827530249eb6825595e3549f8058913d9f21e 100644
--- a/bob/bio/vein/algorithms/HammingDistance.py
+++ b/bob/bio/vein/algorithms/HammingDistance.py
@@ -18,7 +18,6 @@ class HammingDistance (Algorithm):
       # some similarity functions might need a GaborWaveletTransform class, so we have to provide the parameters here as well...
       ch = 8,       # Maximum search displacement in y-direction
       cw = 5,       # Maximum search displacement in x-direction
-      gpu = False,
   ):
 
     # call base class constructor
@@ -34,7 +33,6 @@ class HammingDistance (Algorithm):
 
     self.ch = ch
     self.cw = cw
-    self.gpu = gpu
 
   def enroll(self, enroll_features):
     """Enrolls the model by computing an average graph for each model"""
@@ -54,11 +52,7 @@ class HammingDistance (Algorithm):
     bob.ip.base.rotate(crop_R, rotate_R, 180)
     #FFT for scoring!
     #Nm=bob.sp.ifft(bob.sp.fft(I)*bob.sp.fft(rotate_R))
-    if self.gpu == True:
-        import xbob.cusp
-        Nm = xbob.cusp.conv(I, rotate_R);
-    else:
-        Nm = scipy.signal.convolve2d(I, rotate_R, 'valid');
+    Nm = scipy.signal.convolve2d(I, rotate_R, 'valid');
     t0, s0 = numpy.unravel_index(Nm.argmax(), Nm.shape)
     Nmm = Nm[t0,s0]
     #Nmm = Nm.max()
diff --git a/bob/bio/vein/algorithms/MiuraMatch.py b/bob/bio/vein/algorithms/MiuraMatch.py
index 17068bb7a20b75b29c1c45c8582f86bd78cfc99c..3f22338532586b4e016c8b6de9d4136da23069c2 100644
--- a/bob/bio/vein/algorithms/MiuraMatch.py
+++ b/bob/bio/vein/algorithms/MiuraMatch.py
@@ -24,7 +24,6 @@ class MiuraMatch (Algorithm):
       # some similarity functions might need a GaborWaveletTransform class, so we have to provide the parameters here as well...
       ch = 8,       # Maximum search displacement in y-direction
       cw = 5,       # Maximum search displacement in x-direction
-      gpu = False,
       ):
 
     # call base class constructor
@@ -40,7 +39,6 @@ class MiuraMatch (Algorithm):
 
     self.ch = ch
     self.cw = cw
-    self.gpu = gpu
 
 
   def enroll(self, enroll_features):
@@ -95,13 +93,8 @@ class MiuraMatch (Algorithm):
       bob.ip.base.rotate(crop_R, rotate_R, 180)
       #FFT for scoring!
       #Nm=bob.sp.ifft(bob.sp.fft(I)*bob.sp.fft(rotate_R))
-      if self.gpu == True:
-          Nm = self.convfft(I, rotate_R)
-          #import xbob.cusp
-          #Nm = xbob.cusp.conv(I, rotate_R);
-      else:
-          Nm = self.convfft(I, rotate_R)
-          #Nm2 = scipy.signal.convolve2d(I, rotate_R, 'valid')
+      Nm = self.convfft(I, rotate_R)
+      #Nm2 = scipy.signal.convolve2d(I, rotate_R, 'valid')
 
       t0, s0 = numpy.unravel_index(Nm.argmax(), Nm.shape)
       Nmm = Nm[t0,s0]
diff --git a/bob/bio/vein/configurations/algorithms.py b/bob/bio/vein/configurations/algorithms.py
index 483949bc96261bdb48c58912aca095fa7264e92f..21d8f6e2955a43f38dc1533c6150e7750e19b896 100644
--- a/bob/bio/vein/configurations/algorithms.py
+++ b/bob/bio/vein/configurations/algorithms.py
@@ -3,9 +3,6 @@
 
 from ..algorithms import MiuraMatch
 
-huangwl_tool = MiuraMatch(ch=18, cw=28)
-huangwl_gpu_tool = MiuraMatch(ch=18, cw=28, gpu=True)
-miuramax_tool = MiuraMatch(ch=80, cw=90)
-miuramax_gpu_tool = MiuraMatch(ch=80, cw=90, gpu=True)
-miurarlt_tool = MiuraMatch(ch=65, cw=55)
-miurarlt_gpu_tool = MiuraMatch(ch=65, cw=55, gpu=True)
+huangwl = MiuraMatch(ch=18, cw=28)
+miuramax = MiuraMatch(ch=80, cw=90)
+miurarlt = MiuraMatch(ch=65, cw=55)
diff --git a/bob/bio/vein/configurations/extractors/maximum_curvature.py b/bob/bio/vein/configurations/extractors/maximum_curvature.py
index a5eed574e27f98c4217644b3dddbfb58c05ad5fe..96203b3930b71f3476d54637e5df061608636ad0 100644
--- a/bob/bio/vein/configurations/extractors/maximum_curvature.py
+++ b/bob/bio/vein/configurations/extractors/maximum_curvature.py
@@ -2,15 +2,4 @@
 # vim: set fileencoding=utf-8 :
 
 from ...extractors import MaximumCurvature
-
-
-# Parameters
-SIGMA_DERIVATES = 5 #Sigma used for determining derivatives
-
-GPU_ACCELERATION = False
-
-#Define feature extractor
-feature_extractor = MaximumCurvature(
-    sigma = SIGMA_DERIVATES,
-    gpu = GPU_ACCELERATION,
-    )
+feature_extractor = MaximumCurvature(sigma = 5)
diff --git a/bob/bio/vein/configurations/grid/gpu.py b/bob/bio/vein/configurations/grid/gpu.py
deleted file mode 100644
index 5ca10c5aa22564cd9061f5d1dd50474df8f7bb89..0000000000000000000000000000000000000000
--- a/bob/bio/vein/configurations/grid/gpu.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-
-import bob.bio.base.grid import Grid
-
-
-grid = Grid(
-    training_queue = '8G',
-
-    number_of_preprocessing_jobs = 32,
-    preprocessing_queue = '4G-io-big',
-
-    number_of_extraction_jobs = 32,
-    extraction_queue = '4G-io-big',
-
-    number_of_projection_jobs = 32,
-    projection_queue = {},
-
-    number_of_enrollment_jobs = 32,
-    enrollment_queue = {},
-
-    number_of_scoring_jobs = 32,
-    scoring_queue = {'queue': 'q_gpu'},
-    )
diff --git a/bob/bio/vein/configurations/grid/gpu2.py b/bob/bio/vein/configurations/grid/gpu2.py
deleted file mode 100644
index 02d04550a99a65c35de14e006d7a655ed8580420..0000000000000000000000000000000000000000
--- a/bob/bio/vein/configurations/grid/gpu2.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-
-import bob.bio.base.grid import Grid
-
-
-grid = Grid(
-    training_queue = '8G',
-
-    number_of_preprocessing_jobs = 32,
-    preprocessing_queue = '4G-io-big',
-
-    number_of_extraction_jobs = 32,
-    extraction_queue = '4G-io-big',
-
-    number_of_projection_jobs = 32,
-    projection_queue = {},
-
-    number_of_enrollment_jobs = 32,
-    enrollment_queue = {},
-
-    number_of_scoring_jobs = 32,
-    scoring_queue = '4G-io-big',
-    )
diff --git a/bob/bio/vein/configurations/grid/gpu3.py b/bob/bio/vein/configurations/grid/gpu3.py
deleted file mode 100644
index 4d0d2b972ad378da404f3f4e521264900d8dd2af..0000000000000000000000000000000000000000
--- a/bob/bio/vein/configurations/grid/gpu3.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-
-import bob.bio.base.grid import Grid
-
-
-grid = Grid(
-    training_queue = '8G',
-
-    number_of_preprocessing_jobs = 1000,
-    preprocessing_queue = {},
-
-    number_of_extraction_jobs = 1000,
-    extraction_queue = {},
-
-    number_of_projection_jobs = 1000,
-    projection_queue = {},
-
-    number_of_enrollment_jobs = 100,
-    enrollment_queue = '2G',
-
-    number_of_scoring_jobs = 1500,
-    scoring_queue = {'queue': 'q_gpu'},
-    )
diff --git a/bob/bio/vein/configurations/preprocessors/finger_crop_None_CircGabor.py b/bob/bio/vein/configurations/preprocessors/finger_crop_None_CircGabor.py
index 909a31ea2a5ea623bcf6a0e3036d8637dd19aea7..da45dd702e4a2ac25e02877885d262f7fcc09007 100644
--- a/bob/bio/vein/configurations/preprocessors/finger_crop_None_CircGabor.py
+++ b/bob/bio/vein/configurations/preprocessors/finger_crop_None_CircGabor.py
@@ -10,20 +10,15 @@ CONTOUR_MASK_WIDTH = 40 # Width of the mask
 PADDING_OFFSET = 5
 PADDING_THRESHOLD = 0.2 #Threshold for padding black zones
 
-PREPROCESSING = None
 FINGERCONTOUR = 'leemaskMod' # Options: 'leemaskMatlab', 'konomask'
 POSTPROCESSING = 'CircGabor' # Options: None, 'HE', 'HFE', 'CircGabor'
 
-GPU_ACCELERATION = False
-
 # define the preprocessor
 preprocessor = FingerCrop(
     mask_h=CONTOUR_MASK_HEIGHT,
     mask_w=CONTOUR_MASK_WIDTH,
     padding_offset=PADDING_OFFSET,
     padding_threshold=PADDING_THRESHOLD,
-    preprocessing=PREPROCESSING,
     fingercontour=FINGERCONTOUR,
     postprocessing=POSTPROCESSING,
-    gpu=GPU_ACCELERATION,
     )
diff --git a/bob/bio/vein/configurations/preprocessors/finger_crop_None_HE.py b/bob/bio/vein/configurations/preprocessors/finger_crop_None_HE.py
index 8b317a71142be5612a5c11fe70b2168317805759..8abf66a78d252c30d9200bb1e6d39a4521bac747 100644
--- a/bob/bio/vein/configurations/preprocessors/finger_crop_None_HE.py
+++ b/bob/bio/vein/configurations/preprocessors/finger_crop_None_HE.py
@@ -14,16 +14,12 @@ PREPROCESSING = None
 FINGERCONTOUR = 'leemaskMod' # Options: 'leemaskMatlab', 'konomask'
 POSTPROCESSING = 'HE' 		 # Options: None, 'HE', 'HFE', 'CircGabor'
 
-GPU_ACCELERATION = False
-
 # define the preprocessor
 preprocessor = FingerCrop(
     mask_h=CONTOUR_MASK_HEIGHT,
     mask_w=CONTOUR_MASK_WIDTH,
     padding_offset=PADDING_OFFSET,
     padding_threshold=PADDING_THRESHOLD,
-    preprocessing=PREPROCESSING,
     fingercontour=FINGERCONTOUR,
     postprocessing=POSTPROCESSING,
-    gpu=GPU_ACCELERATION
     )
diff --git a/bob/bio/vein/configurations/preprocessors/finger_crop_None_HFE.py b/bob/bio/vein/configurations/preprocessors/finger_crop_None_HFE.py
index e12d1f392dec5bebd36fc1dffc064a305c45a27a..023aba1fbad0a8e6e6984d51844fbd018407cd12 100644
--- a/bob/bio/vein/configurations/preprocessors/finger_crop_None_HFE.py
+++ b/bob/bio/vein/configurations/preprocessors/finger_crop_None_HFE.py
@@ -15,8 +15,6 @@ PREPROCESSING = None
 FINGERCONTOUR = 'leemaskMod' # Options: 'leemaskMatlab', 'konomask'
 POSTPROCESSING = 'HFE' 		 # Options: None, 'HE', 'HFE', 'CircGabor'
 
-GPU_ACCELERATION = False
-
 # define the preprocessor
 preprocessor = FingerCrop(
     mask_h=CONTOUR_MASK_HEIGHT,
@@ -26,5 +24,4 @@ preprocessor = FingerCrop(
     preprocessing=PREPROCESSING,
     fingercontour=FINGERCONTOUR,
     postprocessing=POSTPROCESSING,
-    gpu=GPU_ACCELERATION,
     )
diff --git a/bob/bio/vein/configurations/preprocessors/finger_crop_None_None.py b/bob/bio/vein/configurations/preprocessors/finger_crop_None_None.py
index 9366aa66846220ab4b81090fb0f515781cb5c1f9..dc88fda131a4bc41f726be2f81f7802623adeb7b 100644
--- a/bob/bio/vein/configurations/preprocessors/finger_crop_None_None.py
+++ b/bob/bio/vein/configurations/preprocessors/finger_crop_None_None.py
@@ -11,20 +11,15 @@ CONTOUR_MASK_WIDTH = 40 # Width of the mask
 PADDING_OFFSET = 5
 PADDING_THRESHOLD = 0.2 #Threshold for padding black zones
 
-PREPROCESSING = None
 FINGERCONTOUR = 'leemaskMod' # Options: 'leemaskMod', leemaskMatlab', 'konomask'
 POSTPROCESSING = None 		 # Options: None, 'HE', 'HFE', 'CircGabor'
 
-GPU_ACCELERATION = False
-
 # define the preprocessor
 preprocessor = FingerCrop(
     mask_h=CONTOUR_MASK_HEIGHT,
     mask_w=CONTOUR_MASK_WIDTH,
     padding_offset=PADDING_OFFSET,
     padding_threshold=PADDING_THRESHOLD,
-    preprocessing=PREPROCESSING,
     fingercontour=FINGERCONTOUR,
     postprocessing=POSTPROCESSING,
-    gpu=GPU_ACCELERATION
     )
diff --git a/bob/bio/vein/extractors/MaximumCurvature.py b/bob/bio/vein/extractors/MaximumCurvature.py
index 326231f463d8c673902ddf5e8bfd47296f58884f..fc5d880ef142251ac88e9319f97089f363fb2e18 100644
--- a/bob/bio/vein/extractors/MaximumCurvature.py
+++ b/bob/bio/vein/extractors/MaximumCurvature.py
@@ -18,25 +18,17 @@ class MaximumCurvature (Extractor):
   Based on N. Miura, A. Nagasaka, and T. Miyatake, Extraction of Finger-Vein
   Pattern Using Maximum Curvature Points in Image Profiles. Proceedings on IAPR
   conference on machine vision applications, 9 (2005), pp. 347--350
-  """
 
+  Parameters:
+
+    sigma (int, Optional): Sigma used for determining derivatives
 
-  def __init__(
-      self,
-      sigma = 5, #Sigma used for determining derivatives
-      gpu = False
-  ):
+  """
 
-    # call base class constructor
-    Extractor.__init__(
-        self,
-        sigma = sigma,
-        gpu = gpu
-    )
 
-    # block parameters
+  def __init__(self, sigma = 5):
+    Extractor.__init__(self, sigma = sigma)
     self.sigma = sigma
-    self.gpu = gpu
 
 
   def maximum_curvature(self, image, mask):
@@ -65,11 +57,11 @@ class MaximumCurvature (Extractor):
 
     # Do the actual filtering
 
-    fx = utils.imfilter(image, hx, self.gpu, conv=False)
-    fxx = utils.imfilter(image, hxx, self.gpu, conv=False)
-    fy = utils.imfilter(image, hy, self.gpu, conv=False)
-    fyy = utils.imfilter(image, hyy, self.gpu, conv=False)
-    fxy = utils.imfilter(image, hxy, self.gpu, conv=False)
+    fx = utils.imfilter(image, hx, conv=False)
+    fxx = utils.imfilter(image, hxx, conv=False)
+    fy = utils.imfilter(image, hy, conv=False)
+    fyy = utils.imfilter(image, hyy, conv=False)
+    fxy = utils.imfilter(image, hxy, conv=False)
 
     f1  = 0.5*numpy.sqrt(2)*(fx + fy)   # \  #
     f2  = 0.5*numpy.sqrt(2)*(fx - fy)   # /  #
@@ -263,7 +255,7 @@ class MaximumCurvature (Extractor):
   def __call__(self, image):
     """Reads the input image, extract the features based on Maximum Curvature of the fingervein image, and writes the resulting template"""
 
-    finger_image = image[0]    #Normalized image with or without histogram equalization
+    finger_image = image[0] #Normalized image with or without histogram equalization
     finger_mask = image[1]
 
     return self.maximum_curvature(finger_image, finger_mask)
diff --git a/bob/bio/vein/extractors/PrincipalCurvature.py b/bob/bio/vein/extractors/PrincipalCurvature.py
index 54aa4f61f6bd26ab09d721f94e0f65d4def01fd7..c08cae315ea7e2c571cfe17565372f50962cc24c 100644
--- a/bob/bio/vein/extractors/PrincipalCurvature.py
+++ b/bob/bio/vein/extractors/PrincipalCurvature.py
@@ -20,7 +20,6 @@ class PrincipalCurvature (Extractor):
       self,
       sigma = 2, # Gaussian standard deviation applied
       threshold = 1.3, # Percentage of maximum used for hard thresholding
-      gpu = False,
       ):
 
     # call base class constructor
@@ -28,13 +27,11 @@ class PrincipalCurvature (Extractor):
         self,
         sigma = sigma,
         threshold = threshold,
-        gpu = gpu,
         )
 
     # block parameters
     self.sigma = sigma
     self.threshold = threshold
-    self.gpu = gpu
 
 
   def principal_curvature(self, image, mask):
diff --git a/bob/bio/vein/extractors/__init__.py b/bob/bio/vein/extractors/__init__.py
index 2972d22ba8c07b9022e01571104f9f85a70c41c5..afd52d096a2f4237817de10f43cc3a47c994ec5b 100644
--- a/bob/bio/vein/extractors/__init__.py
+++ b/bob/bio/vein/extractors/__init__.py
@@ -3,6 +3,7 @@ from .NormalisedCrossCorrelation import NormalisedCrossCorrelation
 from .PrincipalCurvature import PrincipalCurvature
 from .RepeatedLineTracking import RepeatedLineTracking
 from .WideLineDetector import WideLineDetector
+from .MaximumCurvature import MaximumCurvature
 
 # gets sphinx autodoc done right - don't remove it
 __all__ = [_ for _ in dir() if not _.startswith('_')]
diff --git a/bob/bio/vein/preprocessors/FingerCrop.py b/bob/bio/vein/preprocessors/FingerCrop.py
index b7ce23a49d827d541fc5b59aa68dea09e57e7fc6..37de9f48d3f56c29a714b303a8a6c31ffa74eb47 100644
--- a/bob/bio/vein/preprocessors/FingerCrop.py
+++ b/bob/bio/vein/preprocessors/FingerCrop.py
@@ -17,14 +17,41 @@ from .. import utils
 
 
 class FingerCrop (Preprocessor):
-  """Fingervein mask
+  """Extracts the mask and pre-processes fingervein images
 
   Based on the implementation: E.C. Lee, H.C. Lee and K.R. Park. Finger vein
   recognition using minutia-based alignment and local binary pattern-based
   feature extraction. International Journal of Imaging Systems and
   Technology. Vol. 19, No. 3, pp. 175-178, September 2009.
+
+
+  Parameters:
+
+    mask_h (int, Optional): Height of contour mask in pixels
+
+    mask_w (int, Optional): Width of the contour mask in pixels
+
+    padding_offset (int, Optional):
+
+    padding_threshold (float, Optional):
+
+    fingercontour (str, Optional): Select between three finger contour
+      implementations: leemaskMod, leemaskMatlab or konomask. (From Pedro Tome:
+      the option ``leemaskMatlab`` was just implemented for testing purposes so
+      we could compare with MAT files generated from Matlab code of other
+      authors. He only used it with the UTFVP database, using ``leemaskMod``
+      with that database yields slight worse results.)
+
+    postprocessing (str, Optional): Select between ``HE`` (histogram
+      equalization, as with :py:func:`bob.ip.base.histogram_equalization`),
+      ``HFE`` (high-frequency emphasis filter, with hard-coded parameters - see
+      implementation) or ``CircGabor`` (circular Gabor filter with band-width
+      1.12 octaves and standard deviation of 5 pixels (this is hard-coded). By
+      default, no postprocessing is applied on the image.
+
   """
 
+
   def __init__(
       self,
       mask_h = 4, # Height of the mask
@@ -33,56 +60,33 @@ class FingerCrop (Preprocessor):
       padding_offset = 5,     #Always the same
       padding_threshold = 0.2,  #0 for UTFVP database (high quality), 0.2 for VERA database (low quality)
 
-      preprocessing = None,
-      fingercontour = 'leemaskMatlab',
+      fingercontour = 'leemaskMod',
       postprocessing = None,
 
-      gpu = False,
-      color_channel = 'gray',    # the color channel to extract from colored images, if colored images are in the database
-      **kwargs                   # parameters to be written in the __str__ method
+      **kwargs
   ):
     """Parameters of the constructor of this preprocessor:
 
-    color_channel
-      In case of color images, which color channel should be used?
-
-    mask_h
-      Height of the cropped mask of a fingervein image
-
-    mask_w
-      Height of the cropped mask of a fingervein image
-
     """
 
-    # call base class constructor
-    Preprocessor.__init__(
-        self,
+    Preprocessor.__init__(self,
         mask_h = mask_h,
         mask_w = mask_w,
-
         padding_offset = padding_offset,
         padding_threshold = padding_threshold,
-
-        preprocessing = preprocessing,
         fingercontour = fingercontour,
         postprocessing = postprocessing,
-
-        gpu = gpu,
-        color_channel = color_channel,
         **kwargs
-    )
+        )
 
     self.mask_h = mask_h
     self.mask_w = mask_w
 
-    self.preprocessing = preprocessing
     self.fingercontour = fingercontour
     self.postprocessing = postprocessing
 
     self.padding_offset = padding_offset
     self.padding_threshold = padding_threshold
-    self.gpu = gpu
-    self.color_channel = color_channel
 
 
   def __konomask__(self, image, sigma):
@@ -109,7 +113,7 @@ class FingerCrop (Preprocessor):
     hy = (-Y/(2*math.pi*sigma**4))*numpy.exp(-(X**2 + Y**2)/(2*sigma**2))
 
     # Filter the image with the directional kernel
-    fy = utils.imfilter(image, hy, self.gpu, conv=False)
+    fy = utils.imfilter(image, hy, conv=False)
 
     # Upper part of filtred image
     img_filt_up = fy[0:half_img_h,:]
@@ -155,7 +159,7 @@ class FingerCrop (Preprocessor):
     mask[0:self.mask_h/2,:] = -1
     mask[self.mask_h/2:,:] = 1
 
-    img_filt = utils.imfilter(image, mask, self.gpu, conv=True)
+    img_filt = utils.imfilter(image, mask, conv=True)
 
     # Upper part of filtred image
     img_filt_up = img_filt[0:half_img_h-1,:]
@@ -165,7 +169,7 @@ class FingerCrop (Preprocessor):
     img_filt_lo = img_filt[half_img_h-1:,:]
     y_lo = img_filt_lo.argmin(axis=0)
 
-    img_filt = utils.imfilter(image, mask.T, self.gpu, conv=True)
+    img_filt = utils.imfilter(image, mask.T, conv=True)
 
         # Left part of filtered image
     img_filt_lf = img_filt[:,0:half_img_w]
@@ -215,7 +219,7 @@ class FingerCrop (Preprocessor):
     mask[0:self.mask_h/2,:] = -1
     mask[self.mask_h/2:,:] = 1
 
-    img_filt = utils.imfilter(image, mask, self.gpu, conv=True)
+    img_filt = utils.imfilter(image, mask, conv=True)
 
     # Upper part of filtred image
     img_filt_up = img_filt[0:numpy.floor(img_h/2),:]
@@ -228,6 +232,7 @@ class FingerCrop (Preprocessor):
     for i in range(0,y_up.size):
         img_filt[y_up[i]:y_lo[i]+img_filt_lo.shape[0],i]=1
 
+    import ipdb; ipdb.set_trace()
     finger_mask = numpy.ndarray(image.shape, numpy.bool)
     finger_mask[:,:] = False
 
@@ -321,30 +326,51 @@ class FingerCrop (Preprocessor):
     return bob.core.convert(image_new,numpy.uint8,(0,255),(0,1))
 
 
-  def __CLAHE__(self, image):
-    """  Contrast-limited adaptive histogram equalization (CLAHE).
-    """
-    #TODO
-    return true
+  def __HE__(self, image):
+    """Applies histogram equalization on the input image
 
 
-  def __HE__(self, image):
-    #Umbralization based on the pixels non zero
-    imageEnhance = numpy.zeros(image.shape)
-    imageEnhance = imageEnhance.astype(numpy.uint8)
+    Parameters:
+
+        image (numpy.ndarray): raw image to be filtered, as 2D array of
+          unsigned 8-bit integers
+
+
+    Returns:
 
-    bob.ip.base.histogram_equalization(image, imageEnhance)
+        numpy.ndarray: normalized image as a 2D array of unsigned 8-bit
+        integers
 
-    return imageEnhance
+    """
+
+    #Umbralization based on the pixels non zero
+    retval = numpy.zeros(image.shape, dtype=numpy.uint8)
+    bob.ip.base.histogram_equalization(image, retval)
+    return retval
 
 
   def __circularGabor__(self, image, bw, sigma):
-    """ CIRCULARGABOR Construct a circular gabor filter
+    """Applies a circular gabor filter on the input image, with parameters
+
+
     Parameters:
-        bw    = bandwidth, (1.12 octave)
-        sigma = standard deviation, (5  pixels)
+
+        image (numpy.ndarray): raw image to be filtered, as 2D array of
+          unsigned 8-bit integers
+
+        bw (float): bandwidth (1.12 octave)
+
+        sigma (int): standard deviation (5  pixels)
+
+
+    Returns:
+
+        numpy.ndarray: normalized image as a 2D array of unsigned 8-bit
+        integers
+
     """
-    #Convert image to doubles
+
+    # Converts image to doubles
     image_new = bob.core.convert(image,numpy.float64,(0,1),(0,255))
     img_h, img_w = image_new.shape
 
@@ -352,10 +378,9 @@ class FingerCrop (Preprocessor):
 
     sz = numpy.fix(8*numpy.max([sigma,sigma]))
 
-    if numpy.mod(sz,2) == 0:
-      sz = sz+1
+    if numpy.mod(sz,2) == 0: sz = sz+1
 
-    #Construct filter kernel
+    #Constructs filter kernel
     winsize = numpy.fix(sz/2)
 
     x = numpy.arange(-winsize, winsize+1)
@@ -369,26 +394,26 @@ class FingerCrop (Preprocessor):
     # Without normalisation
     #gaborfilter = numpy.exp(-0.5*(X**2/sigma**2+Y**2/sigma**2))*numpy.cos(2*math.pi*fc*numpy.sqrt(X**2+Y**2))
 
-    imageEnhance = utils.imfilter(image, gaborfilter, self.gpu, conv=False)
+    imageEnhance = utils.imfilter(image, gaborfilter, conv=False)
     imageEnhance = numpy.abs(imageEnhance)
 
-    imageEnhance = bob.core.convert(imageEnhance,numpy.uint8,(0,255),(imageEnhance.min(),imageEnhance.max()))
-
-    return imageEnhance
+    return bob.core.convert(imageEnhance,numpy.uint8, (0,255),
+        (imageEnhance.min(),imageEnhance.max()))
 
 
   def __HFE__(self,image):
-    """ High Frequency Enphasis Filtering (HFE)
+    """ High Frequency Emphasis Filtering (HFE)
 
     """
-    ### Parameters
+
+    ### Hard-coded parameters for the HFE filtering
     D0 = 0.025
     a = 0.6
     b = 1.2
     n = 2.0
 
-    #Convert image to doubles
-    image_new = bob.core.convert(image,numpy.float64,(0,1),(0,255))
+    # converts image to doubles
+    image_new = bob.core.convert(image,numpy.float64, (0,1), (0,255))
     img_h, img_w = image_new.shape
 
     # DFT
@@ -399,123 +424,67 @@ class FingerCrop (Preprocessor):
     col = numpy.arange(1,img_h+1)
     y =  (numpy.tile(col,(img_w,1)).T - (numpy.fix(img_h/2)+1))/img_h
 
-    #D  is  the  distance  from  point  (u,v)  to  the  centre  of the frequency rectangle.
+    # D  is  the  distance  from  point  (u,v)  to  the  centre  of the
+    # frequency rectangle.
     radius = numpy.sqrt(x**2 + y**2)
 
     f = a + b / (1.0 + (D0 / radius)**(2*n))
     Ffreq = Ffreq * f
-    #Inverse DFT
-    imageEnhance = bob.sp.ifft(bob.sp.ifftshift(Ffreq))
-    #Skip complex part
-    imageEnhance = numpy.abs(imageEnhance)
-
-    #To solve errors
-    imageEnhance = bob.core.convert(imageEnhance,numpy.uint8,(0,255),(imageEnhance.min(),imageEnhance.max()))
-
-    return imageEnhance
-
-
-  def __spoofingdetector__(self, image):
-    #Histogram equalization to normalize
-    imageEnhance = numpy.zeros(image.shape)
-    imageEnhance = imageEnhance.astype(numpy.uint8)
-
-    bob.ip.base.histogram_equalization(image, imageEnhance)
-
-    #Convert image to doubles
-    image_new = bob.core.convert(imageEnhance,numpy.float64,(0,1),(0,255))
-
-    img_h, img_w = image_new.shape
-
-    # Determine lower half starting point vertically
-    if numpy.mod(img_h,2) == 0:
-        half_img_h = img_h/2 + 1
-    else:
-        half_img_h = numpy.ceil(img_h/2)
 
-    # Determine lower half starting point horizontally
-    if numpy.mod(img_w,2) == 0:
-        half_img_w = img_w/2 + 1
-    else:
-        half_img_w = numpy.ceil(img_w/2)
-
-    Ffreq = bob.sp.fftshift(bob.sp.fft(image_new.astype(numpy.complex128))/math.sqrt(img_h*img_w))
-    F = numpy.log10(abs(Ffreq)**2)
-
-    offset_window = 10
-    img_half_section_v = F[:,(half_img_w-offset_window):(half_img_w+offset_window)]
-
-    pv = numpy.mean(img_half_section_v,1)
-
-    dBthreshold = -3
-    Bwv = numpy.size(numpy.where(pv>dBthreshold))*1.0 / img_h
+    # implements the inverse DFT
+    imageEnhance = bob.sp.ifft(bob.sp.ifftshift(Ffreq))
 
-    return Bwv
+    # skips complex part
+    imageEnhance = numpy.abs(imageEnhance)
 
+    # renormalizes and returns
+    return bob.core.convert(imageEnhance, numpy.uint8, (0, 255),
+        (imageEnhance.min(), imageEnhance.max()))
 
-  def crop_finger(self, image):
 
-    spoofingValue = self.__spoofingdetector__(image)
+  def __call__(self, image, annotations=None):
+    """Reads the input image, extract the mask of the fingervein, postprocesses
+    """
 
-    #Padding array
+    # Padding array
     image = self.__padding_finger__(image)
 
-    ## Fingervein image enhancement:
-    if self.preprocessing != None:
-      if self.preprocessing == 'CLAHE':
-        image_eq = self.__CLAHE__(image)
-      elif self.preprocessing == 'HE':
-        image_eq = self.__HE__(image)
-      elif self.preprocessing == 'HFE':
-        image_eq = self.__HFE__(image)
-      elif self.preprocessing == 'CircGabor':
-        image_eq = self.__circularGabor__(image, 1.12, 5)
-    else: image_eq = image
-
     ## Finger edges and contour extraction:
     if self.fingercontour == 'leemaskMatlab':
-      finger_mask, finger_edges = self.__leemaskMatlab__(image_eq)        #Function for UTFVP
+      finger_mask, finger_edges = self.__leemaskMatlab__(image) #for UTFVP
     elif self.fingercontour == 'leemaskMod':
-      finger_mask, finger_edges = self.__leemaskMod__(image_eq)            #Function for VERA
+      finger_mask, finger_edges = self.__leemaskMod__(image) #for VERA
     elif self.fingercontour == 'konomask':
-      finger_mask, finger_edges = self.__konomask__(image_eq, sigma=5)
+      finger_mask, finger_edges = self.__konomask__(image, sigma=5)
 
     ## Finger region normalization:
-    image_norm,finger_mask_norm = self.__huangnormalization__(image_eq, finger_mask, finger_edges)
+    image_norm, finger_mask_norm = self.__huangnormalization__(image,
+        finger_mask, finger_edges)
 
     ## veins enhancement:
-    if self.postprocessing != None:
-      if self.postprocessing == 'CLAHE':
-        image_norm = self.__CLAHE__(image_norm)
-      elif self.postprocessing == 'HE':
-        image_norm = self.__HE__(image_norm)
-      elif self.postprocessing == 'HFE':
-        image_norm = self.__HFE__(image_norm)
-      elif self.postprocessing == 'CircGabor':
-        image_norm = self.__circularGabor__(image_norm, 1.12, 5)
-
+    if self.postprocessing == 'HE':
+      image_norm = self.__HE__(image_norm)
+    elif self.postprocessing == 'HFE':
+      image_norm = self.__HFE__(image_norm)
+    elif self.postprocessing == 'CircGabor':
+      image_norm = self.__circularGabor__(image_norm, 1.12, 5)
 
-    #To check the mask:
-    finger_mask2 = bob.core.convert(finger_mask,numpy.uint8,(0,255),(0,1))
+    ## returns the normalized image and the finger mask
+    return image_norm, finger_mask_norm
 
-    return (image_norm, finger_mask_norm, finger_mask2, spoofingValue)
 
+  def write_data(self, data, filename):
+    '''Overrides the default method implementation to handle our tuple'''
 
-  def __call__(self, image, annotations=None):
-    """Reads the input image, extract the Lee mask of the fingervein, and writes the resulting image"""
-    return self.crop_finger(image)
-
+    f = bob.io.base.HDF5File(filename, 'w')
+    f.set('image', data[0])
+    f.set('finger_mask', data[1])
 
-  def write_data(self, image, image_file):
-    f = bob.io.base.HDF5File(image_file, 'w')
-    f.set('image', image[0])
-    f.set('finger_mask', image[1])
-    f.set('mask', image[2])
-    f.set('spoofingValue', image[3])
 
+  def read_data(self, filename):
+    '''Overrides the default method implementation to handle our tuple'''
 
-  def read_data(self, image_file):
-    f = bob.io.base.HDF5File(image_file, 'r')
+    f = bob.io.base.HDF5File(filename, 'r')
     image = f.read('image')
     finger_mask = f.read('finger_mask')
     return (image, finger_mask)
diff --git a/bob/bio/vein/tests/test.py b/bob/bio/vein/tests/test.py
index 20a5eaf632e1b885028c264d68b68b626401d646..af994132d1a1ea66d73e29212c2c765978e1b4e9 100644
--- a/bob/bio/vein/tests/test.py
+++ b/bob/bio/vein/tests/test.py
@@ -2,7 +2,14 @@
 # vim: set fileencoding=utf-8 :
 
 
-"""Test Units
+"""Unit tests against references extracted from
+
+Matlab code from Bram Ton available on the matlab central website:
+
+https://www.mathworks.com/matlabcentral/fileexchange/35754-wide-line-detector
+
+This code implements the detector described in [HDLTL10] (see the references in
+the generated sphinx documentation)
 """
 
 import os
@@ -24,8 +31,6 @@ def F(parts):
 
 def test_finger_crop():
 
-  #Test finger vein image preprocessors
-
   input_filename = F(('preprocessors', '0019_3_1_120509-160517.png'))
   output_img_filename  = F(('preprocessors',
     '0019_3_1_120509-160517_img_lee_huang.mat'))
@@ -35,10 +40,9 @@ def test_finger_crop():
   img = bob.io.base.load(input_filename)
 
   from bob.bio.vein.preprocessors.FingerCrop import FingerCrop
-  FC = FingerCrop(4, 40, False, False)
-  #FC = FingerCrop(4, 40, False, 5, 0.2, False)
+  preprocess = FingerCrop(fingercontour='leemaskMatlab')
 
-  output_img, finger_mask_norm, finger_mask2, spoofingValue = FC(img)
+  output_img, finger_mask_norm = preprocess(img)
 
   # Load Matlab reference
   output_img_ref = bob.io.base.load(output_img_filename)
@@ -143,11 +147,3 @@ def test_miura_match():
 
   score_imp = MM.score(template_vein, probe_imp_vein)
   assert numpy.isclose(score_imp, 0.172906739278421)
-
-  if False: #testing gpu enabled calculations
-    MM = MiuraMatch(ch=18, cw=28, gpu=True)
-    score_gen = MM.score(template_vein, probe_gen_vein)
-    assert numpy.isclose(score_gen, 0.382689335394127)
-
-    score_imp = MM.score(template_vein, probe_imp_vein)
-    assert numpy.isclose(score_imp, 0.172906739278421)
diff --git a/bob/bio/vein/utils.py b/bob/bio/vein/utils.py
index 7e84f45852e51569045cbb585997593fe5fd216c..4579165d1777230ed4ac1d6e172e3d0b4668d24e 100644
--- a/bob/bio/vein/utils.py
+++ b/bob/bio/vein/utils.py
@@ -8,23 +8,37 @@ import bob.sp
 import bob.core
 
 
-def imfilter(a, b, gpu=False, conv=True):
-  """imfilter function based on MATLAB implementation."""
+def imfilter(a, b, conv=True):
+  """Applies a 2D filtering between images
 
-  if (a.dtype == numpy.uint8):
-      a= bob.core.convert(a,numpy.float64,(0,1))
-  M, N = a.shape
-  if conv == True:
+  This implementation was created to work exactly like the Matlab one.
+
+
+  Parameters:
+
+    a (numpy.ndarray): A 2-dimensional :py:class:`numpy.ndarray` which
+      represents the image to be filtered. The dtype of the array is supposed
+      to be 64-floats. You can also pass an 8-bit unsigned integer array,
+      loaded from a file (for example). In this case it will be scaled as
+      with :py:func:`bob.core.convert` and the range reset to ``[0.0, 1.0]``.
+
+    b (numpy.ndarray): A 64-bit float 2-dimensional :py:class:`numpy.ndarray`
+      which represents the filter to be applied to the image
+
+    conv (bool, Optional): If set, then rotates the filter ``b`` by 180 degrees
+      before applying it to the image ``a``, with
+      :py:func:`bob.ip.base.rotate`.
+
+  """
+
+  if a.dtype == numpy.uint8:
+      a = bob.core.convert(a, numpy.float64, (0,1))
+
+  if conv:
       b = bob.ip.base.rotate(b, 180)
-  shape = numpy.array((0,0))
-  shape[0] = a.shape[0] + b.shape[0] - 1
-  shape[1] = a.shape[1] + b.shape[1] - 1
+
+  shape = (a.shape[0] + b.shape[0] - 1, a.shape[1] + b.shape[1] - 1)
   a_ext = numpy.ndarray(shape=shape, dtype=numpy.float64)
   bob.sp.extrapolate_nearest(a, a_ext)
 
-  if gpu == True:
-    import xbob.cusp
-    return xbob.cusp.conv(a_ext, b)
-  else:
-    return scipy.signal.convolve2d(a_ext, b, 'valid')
-    #return = self.convfft(a_ext, b)
+  return scipy.signal.convolve2d(a_ext, b, 'valid')
diff --git a/buildout.cfg b/buildout.cfg
index 303cff70d1dd40d1f696142cafa2b228ebcd8bf0..20c9a9859bbc4595c906fcf91570de1e839629d8 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -7,6 +7,7 @@ extensions = bob.buildout
 eggs =  bob.bio.vein
         bob.bio.base
         bob.db.base
+        bob.measure
         bob.extension
         gridtk
 develop = src/bob.db.vera
diff --git a/doc/baselines.rst b/doc/baselines.rst
index 049b8f7c76798ca3d6b317e7bb5e3c92df32c1a1..0a6dd3ba4ec181d91fa028412bec8398d5f0190b 100644
--- a/doc/baselines.rst
+++ b/doc/baselines.rst
@@ -75,7 +75,8 @@ Usually it is a good idea to have at least verbose level 2 (i.e., calling
 
 
 In the remainder of this section we introduce baseline experiments you can
-readily run with this tool without further configuration.
+readily run with this tool without further configuration. Baselines examplified
+in this guide were published in [TVM14]_.
 
 
 Repeated Line-Tracking with Miura Matching
@@ -84,24 +85,51 @@ Repeated Line-Tracking with Miura Matching
 You can find the description of this method on the paper from Miura *et al.*
 [MNM04]_.
 
-To run the baseline on the `VERA fingervein`_ database, using the ``1vsAll``
-protocol (1-fold cross-validation), do the following:
+To run the baseline on the `VERA fingervein`_ database, using the ``nom``
+protocol (called ``Full`` in [TVM14]_), do the following:
 
 .. code-block:: sh
 
-   ./bin/verify.py --database=vera --protocol=1vsAll --preprocessor=none --extractor=repeatedlinetracking --algorithm=match-rlt --sub-directory="vera-1vsall-mnm04" --verbose --verbose
+   $ ./bin/verify.py --database=vera --protocol=nom --preprocessor=none --extractor=repeatedlinetracking --algorithm=match-rlt --sub-directory="rlt" --verbose --verbose
 
-This command line selects the following implementations for the toolchain:
+.. tip::
+
+   If you have more processing cores on your local machine and don't want to
+   submit your job for SGE execution, you can run it in parallel by adding the
+   options ``?``.
+
+This command line selects and runs the following implementations for the
+toolchain:
+
+* Database: Use the base Bob API for the VERA database implementation,
+  protocol variant ``nom`` which corresponds to the ``Full`` evaluation
+  protocol described in [TVM14]_
+* Preprocessor: Simple finger cropping, with no extra pre-processing and no
+  histogram equalization, as defined in [LLP09]_
+* Feature extractor: Repeated line tracking, as explained in [MNM04]_
+* Matching algorithm: "Miura" matching, as explained on the same paper
+* Subdirectory: This is the subdirectory in which the scores and intermediate
+  results of this baseline will be stored.
 
-  * Database: Use the base Bob API for the VERA database implementation,
-    protocol variant ``1vsAll`` which corresponds to the 1-fold
-    cross-validation evaluation protocol described in [TVM14]_
-  * Preprocessor: Simple finger cropping, with no extra pre-processing
-  * Feature extractor: Repeated line tracking, as explained in [MNM04]_
-  * Matching algorithm: "Miura" matching, as explained on the same paper
 
 As the tool runs, you'll see printouts that show how it advances through
-preprocessing, feature extraction and matching.
+preprocessing, feature extraction and matching. To complete the evaluation,
+run the commands bellow, that will output the equal error rate (EER) and plot
+the detector error trade-off (DET) curve with the performance:
+
+.. code-block:: sh
+
+   $ ./bin/bob_eval_threshold.py  --scores <path-to>/vera/rlt/nom/nonorm/scores-dev --criterium=eer
+   ('Threshold:', 0.32023322499999995)
+   FAR : 24.318% (46866/192720)
+   FRR : 24.318% (107/440)
+   HTER: 24.318%
+   $ ./bin/evaluate.py --dev-files <path-to>/vera/rlt/nom/nonorm/scores-dev --det det.pdf -l "vera-nom-mnm04" -rr
+   The Recognition Rate of the development set of 'rlt' is 48.409%
+
+To view the DET curve stored in
+
+   $ xdg-open det.pdf #to view the DET curve
 
 
 Available Resources
diff --git a/requirements.txt b/requirements.txt
index dbfb370239a079c02845a712f908039d34b56a43..8dbbc2ff906672b1191eb7616b21252b038362bc 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,6 @@ setuptools
 numpy
 scipy
 pillow
-argparse
 bob.extension
 bob.core
 bob.io.base
diff --git a/setup.py b/setup.py
index 3022b20286be1b9112035f00f9a2ce434c145263..20e9c7bd20560636355a32ebdccc1a4ebf32b312 100644
--- a/setup.py
+++ b/setup.py
@@ -57,12 +57,9 @@ setup(
 
       # registered fingervein recognition algorithms
       'bob.bio.algorithm': [
-        'match-wld = bob.bio.vein.configurations.algorithms:huangwl_tool',
-        'match-wld-gpu = bob.bio.vein.configurations.algorithms:huangwl_gpu_tool',
-        'match-mc = bob.bio.vein.configurations.algorithms:miuramax_tool',
-        'match-mc-gpu = bob.bio.vein.configurations.algorithms:miuramax_gpu_tool',
-        'match-rlt = bob.bio.vein.configurations.algorithms:miurarlt_tool',
-        'match-rlt-gpu = bob.bio.vein.configurations.algorithms:miurarlt_gpu_tool',
+        'match-wld = bob.bio.vein.configurations.algorithms:huangwl',
+        'match-mc = bob.bio.vein.configurations.algorithms:miuramax',
+        'match-rlt = bob.bio.vein.configurations.algorithms:miurarlt',
         #'match-lbp = bob.bio.face.configurations.algorithms.lgbphs:tool',
        ],