[med-svn] [mia] 01/11: Imported Upstream version 2.2.3

Gert Wollny gert-guest at moszumanska.debian.org
Wed Jan 14 11:08:14 UTC 2015


This is an automated email from the git hooks/post-receive script.

gert-guest pushed a commit to branch master
in repository mia.

commit 365a5390523c1afe0cff99e4355ba742c3a64695
Author: Gert Wollny <gw.fossdev at gmail.com>
Date:   Wed Jan 7 12:23:35 2015 +0100

    Imported Upstream version 2.2.3
---
 CMakeLists.txt                                     |  14 +-
 ChangeLog                                          |   9 +
 .../test_combiner.cc => addons/jpg/jpeg-common.hh  |  53 ++-
 addons/jpg/jpg-gray.cc                             |  90 ++---
 addons/jpg/jpg-rgb.cc                              |  74 ++---
 addons/nifti/niftiimage.cc                         |  54 +--
 addons/nifti/test_niftiimage.cc                    |   1 +
 cmake/macros.cmake                                 |  98 ++++--
 doc/CMakeLists.txt                                 |  42 ++-
 doc/MiaDoctools.cmake                              | 187 +++++++++++
 doc/__init__.py                                    |   1 +
 doc/extract_docu.py                                | 159 ---------
 doc/mia-xmldoc2man.cmake                           |   5 +
 doc/mia-xmldoc2nipype.cmake                        |   5 +
 doc/miareadxml.py                                  | 168 +++++++++-
 doc/miaxml2html.py                                 | 112 -------
 doc/miaxml2man.py                                  |   7 +-
 doc/miaxml2nipype.py                               | 366 +++++++++++++++++++++
 doc/miaxml2sgml.py                                 |   2 +-
 mia/2d/creator/circle.cc                           |   1 -
 mia/2d/filter.cc                                   |   1 -
 mia/2d/filter/CMakeLists.txt                       |   3 +-
 mia/2d/filter/labelscale.cc                        | 166 ++++++++++
 mia/2d/{test_combiner.cc => filter/labelscale.hh}  |  43 ++-
 mia/2d/filter/test_labelscale.cc                   | 128 +++++++
 mia/2d/filtertest.cc                               |   1 -
 mia/2d/fullcost/CMakeLists.txt                     |   2 +-
 mia/2d/fullcost/label.cc                           | 340 +++++++++++++++++++
 mia/2d/fullcost/label.hh                           |  97 ++++++
 mia/2d/fullcost/test_label.cc                      | 127 +++++++
 mia/2d/imageiotest.cc                              |   1 -
 mia/2d/imagetest.cc                                |   1 -
 mia/2d/interpolator.cc                             |   2 -
 mia/2d/register.cc                                 |   3 +-
 mia/2d/test_combiner.cc                            |   1 -
 mia/2d/test_distance.cc                            |   1 -
 mia/2d/test_filter.cc                              |   2 +-
 mia/2d/test_filter_cast.cc                         |   1 -
 mia/2d/test_fullcost.cc                            |   4 +-
 mia/2d/test_ica.cc                                 |   1 -
 mia/2d/test_image.cc                               |   2 -
 mia/2d/test_imageio.cc                             |   1 -
 mia/2d/test_interpol.cc                            |   1 -
 mia/2d/test_modelsolverreg.cc                      |   1 -
 mia/2d/test_nfg.cc                                 |   1 -
 mia/2d/test_oldnewintegrate.cc                     |   1 -
 mia/2d/test_ppmatrix.cc                            |  17 +-
 mia/2d/test_regplugins.cc                          |   1 -
 mia/2d/test_segframe.cc                            |   1 -
 mia/2d/test_segmentation.cc                        |   1 -
 mia/2d/test_shape.cc                               |   1 -
 mia/2d/test_transformfactory.cc                    |   1 -
 mia/2d/test_vectorfield_interpolator.cc            |   1 -
 mia/2d/test_vfio.cc                                |   1 -
 mia/2d/vfiotest.cc                                 |   1 -
 mia/3d/datafield.cxx                               |  36 ++
 mia/3d/datafield.hh                                |  14 +
 mia/3d/fifof/morphological.cc                      |   1 -
 mia/3d/fifof/regiongrow.cc                         |   2 +-
 mia/3d/filter.cc                                   |   2 -
 mia/3d/filter/CMakeLists.txt                       |   1 +
 mia/3d/filter/labelscale.cc                        | 177 ++++++++++
 .../test_combiner.cc => 3d/filter/labelscale.hh}   |  43 ++-
 mia/3d/filter/test_bandpass.cc                     |   1 -
 mia/3d/filter/test_binarize.cc                     |   1 -
 mia/3d/filter/test_convert.cc                      |   1 -
 mia/3d/filter/test_crop.cc                         |   1 -
 mia/3d/filter/test_downscale.cc                    |   1 -
 mia/3d/filter/test_gradnorm.cc                     |   1 -
 mia/3d/filter/test_growmask.cc                     |   1 -
 mia/3d/filter/test_invert.cc                       |   1 -
 mia/3d/filter/test_kmeans.cc                       |   1 -
 mia/3d/filter/test_label.cc                        |   1 -
 mia/3d/filter/test_labelscale.cc                   | 169 ++++++++++
 mia/3d/filter/test_load.cc                         |   1 -
 mia/3d/filter/test_mask.cc                         |   1 -
 mia/3d/filter/test_median.cc                       |   1 -
 mia/3d/filter/test_mlv.cc                          |   1 -
 mia/3d/filter/test_morphological.cc                |   1 -
 mia/3d/filter/test_reorient.cc                     |   1 -
 mia/3d/filter/test_scale.cc                        |   1 -
 mia/3d/filter/test_selectbig.cc                    |   1 -
 mia/3d/filter/test_sepconv.cc                      |   1 -
 mia/3d/filter/test_tee.cc                          |   1 -
 mia/3d/fullcost/CMakeLists.txt                     |   2 +-
 mia/3d/fullcost/label.cc                           | 321 ++++++++++++++++++
 mia/3d/fullcost/label.hh                           | 100 ++++++
 mia/3d/fullcost/test_label.cc                      | 203 ++++++++++++
 mia/3d/image.hh                                    |  21 ++
 mia/3d/imageiotest.cc                              |   2 -
 mia/3d/imagetest.cc                                |   1 -
 mia/3d/interpolator.cc                             |   1 -
 mia/3d/multireg.cc                                 |   1 -
 mia/3d/test_combiner.cc                            |   1 -
 mia/3d/test_cost.cc                                |   3 -
 mia/3d/test_deform.cc                              |   2 -
 mia/3d/test_ica.cc                                 |   1 -
 mia/3d/test_image.cc                               |   1 -
 mia/3d/test_interpol.cc                            |   1 -
 mia/3d/test_nfg.cc                                 |   1 -
 mia/3d/test_orientation.cc                         |   3 -
 mia/3d/test_regplugins.cc                          |   1 -
 mia/3d/test_shape.cc                               |   1 -
 mia/3d/test_transformfactory.cc                    |   2 -
 mia/3d/test_vfio.cc                                |   2 -
 mia/3d/transform/rotbend.cc                        |  72 ++--
 mia/3d/transform/rotbend.hh                        |   6 +-
 mia/3d/transform/test_rotbend.cc                   |  12 +-
 mia/3d/vfiotest.cc                                 |   3 +-
 mia/core/CMakeLists.txt                            |   2 +
 mia/core/attributes.hh                             |   6 +-
 mia/core/cmdbooloption.cc                          |   8 +-
 mia/core/cmdbooloption.hh                          |   3 +-
 mia/core/cmdlineparser.cc                          | 182 +++++-----
 mia/core/cmdlineparser.hh                          | 100 ++----
 mia/core/cmdoption.cc                              |  19 +-
 mia/core/cmdoption.hh                              |   5 +-
 mia/core/cmdoptionflags.hh                         |   9 +-
 mia/core/handler.hh                                |  12 +-
 mia/core/minimizer/gdas.cc                         |   9 +-
 mia/core/parameter.cc                              |   6 +-
 .../test_combiner.cc => core/selftestcmdoption.cc} |  33 +-
 mia/core/selftestcmdoption.hh                      |  89 +++++
 mia/core/statistics.hh                             |   2 +-
 mia/core/test_attributes.cc                        |   4 +-
 miacore.pc.cmake                                   |   3 +
 src/2davgmasked.cc                                 |   2 +-
 src/2dcost.cc                                      |   4 +-
 src/2ddistance.cc                                  |  37 ++-
 src/2dgrayimage-combine-to-rgb.cc                  |   2 +-
 src/2dimagecombine-dice.cc                         |   2 +-
 src/2dimagefilter.cc                               |   4 -
 src/2dimagefilterstack.cc                          |   6 -
 src/2dimagefullstats.cc                            |   1 +
 src/2dimageregistration.cc                         |   8 +-
 src/2dimagestats.cc                                |   1 +
 src/2dlerp.cc                                      |  35 +-
 src/2dmany2one-nonrigid.cc                         |   2 +-
 src/2dmulti-force.cc                               |  51 ++-
 src/2dmultiimageregistration.cc                    |  92 ++++++
 src/2dmyocard-ica.cc                               |   3 +-
 src/2dmyocard-icaseries.cc                         |   6 +-
 src/2dmyoseries-compdice.cc                        |   1 +
 src/2dmyoseries-dice.cc                            |   2 +-
 src/2dsegcompare.cc                                |   2 +
 src/2dseghausdorff.cc                              |   1 +
 src/2dsegseriesstats.cc                            |   6 +-
 src/2dseries-mincorr.cc                            |   4 +-
 src/2dseries-segdistance.cc                        |   3 +
 src/2dseries2sets.cc                               |   2 +-
 src/2dserieshausdorff.cc                           |   1 +
 src/2dstackfilter.cc                               |   5 +-
 src/3dcost.cc                                      |   2 +-
 src/3ddistance-stats.cc                            |   5 +-
 src/3dfield2norm.cc                                |   6 +-
 src/3dgetsize.cc                                   |   2 +-
 src/3dgetslice.cc                                  |  21 +-
 src/3dimagecombine.cc                              |   2 +-
 src/3dimagefilter.cc                               |   2 -
 src/3dimagefilterstack.cc                          |   6 +-
 src/3dimagestats.cc                                |   3 +-
 src/3dlandmarks-distances.cc                       |   2 +-
 src/3dlerp.cc                                      |  33 +-
 src/3dnonrigidreg.cc                               |   8 +-
 src/3drigidreg.cc                                  |   8 +-
 src/3dseries-track-intensity.cc                    |   2 +-
 src/3dvfcompare.cc                                 |   6 +-
 src/CMakeLists.txt                                 |  20 +-
 src/__init__.py                                    |   1 +
 src/filenumberpattern.cc                           |   1 +
 src/fluid2d/CMakeLists.txt                         |   3 +-
 src/fluid2d/main.cc                                |   6 +-
 src/fluid3d/CMakeLists.txt                         |   3 +-
 src/fluid3d/main.cc                                |   8 +-
 src/isosurface/CMakeLists.txt                      |   4 +-
 src/meshfilter.cc                                  |   4 -
 src/multihist.cc                                   |   2 +-
 src/myowavelettest.cc                              |   3 +-
 src/plugin-help.cc                                 |   2 +
 src/test_plugins_as_installed.cc                   |   8 +-
 180 files changed, 3563 insertions(+), 1019 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a05f081..2d90774 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,9 +41,9 @@ SET(VENDOR "Gert Wollny")
 SET(PACKAGE_NAME "mia")
 SET(MAJOR_VERSION 2)
 SET(MINOR_VERSION 2)
-SET(MICRO_VERSION 2)
-SET(INTERFACE_AGE 2)
-SET(BINARY_AGE    2)
+SET(MICRO_VERSION 3)
+SET(INTERFACE_AGE 0)
+SET(BINARY_AGE    3)
 
 SET(PACKAGE_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}")
 SET(VERSION "${MAJOR_VERSION}.${MINOR_VERSION}")
@@ -170,7 +170,7 @@ SET(FULL_DOC_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_PATH}")
 SET(BINARY_INSTALL_PATH "${CMAKE_INSTALL_BINDIR}")
 SET(LIBRARY_INSTALL_PATH "${CMAKE_INSTALL_LIBDIR}")
 SET(INCLUDE_INSTALL_PATH "${CMAKE_INSTALL_INCLUDEDIR}/${MIA_NAME}")
-
+SET(MIA_DOCTOOLS_INSTALL_ROOT "${CMAKE_INSTALL_PREFIX}/share/mia-doctools")
 
 ######################################################################################
 #
@@ -437,16 +437,18 @@ ENDIF(ALWAYS_CREATE_DOC)
 #
 # python is needed for creating end-user documentation 
 #
+SET(CREATE_USERDOC FALSE)
+
 FIND_PACKAGE(PythonInterp)
 IF(PYTHONINTERP_FOUND) 
   EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c "import lxml"  RESULT_VARIABLE LXML_ERR)
   IF(LXML_ERR) 
     MESSAGE(python found, but no lxml, no user documantation will be created) 
-    SET(CREATE_USERDOC FALSE)
   ELSE(LXML_ERR)
     SET(CREATE_USERDOC TRUE)
   ENDIF(LXML_ERR) 
-ENDIF(PYTHONINTERP_FOUND) 
+ENDIF(PYTHONINTERP_FOUND)
+
 
 #############################################
 #
diff --git a/ChangeLog b/ChangeLog
index 42b669b..d9bcda2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2.2.3
+
+  New features:
+
+  * Add some more speceliyed 3D image transformations
+  * Install the documentation tools
+  * Add nipype interfaces to all command line tools
+  * Add (localized) normalized cross correlation as cost function
+
 2.2.2
 
   Fixes:
diff --git a/mia/2d/test_combiner.cc b/addons/jpg/jpeg-common.hh
similarity index 52%
copy from mia/2d/test_combiner.cc
copy to addons/jpg/jpeg-common.hh
index ebf7895..3de0e57 100644
--- a/mia/2d/test_combiner.cc
+++ b/addons/jpg/jpeg-common.hh
@@ -18,26 +18,43 @@
  *
  */
 
-#include <stdexcept>
-#include <climits>
+#include <jpeglib.h>
 
-#include <mia/internal/autotest.hh>
-#include <boost/filesystem/path.hpp>
-#include <mia/2d/filter.hh>
+namespace miajpeg {
 
+struct JpegDecompress {
+	
+	JpegDecompress()
+        {
+                info.err = jpeg_std_error(&err);	
+                jpeg_create_decompress(&info);
+        }
+        
+	~JpegDecompress()
+        {
+                jpeg_destroy_decompress(&info);	
+        }
+        
+	struct jpeg_decompress_struct info;
+	struct jpeg_error_mgr err;
+}; 
 
-NS_MIA_USE
-using namespace boost;
-using namespace std;
-namespace bfs=boost::filesystem; 
+struct JpegCompress {
+	
+	JpegCompress()
+        {
+                info.err = jpeg_std_error(&err);	
+                jpeg_create_compress(&info);
+        }
+        
+	~JpegCompress()
+        {
+                jpeg_destroy_compress(&info);	
+        }
 
-BOOST_AUTO_TEST_CASE( test_load_plugins ) 
-{	
-	CPathNameArray plugpath;
-	plugpath.push_back(bfs::path("combiner"));
-	C2DImageCombinerPluginHandler::set_search_path(plugpath);
 
-	const C2DImageCombinerPluginHandler::Instance& handler = C2DImageCombinerPluginHandler::instance(); 
-	BOOST_CHECK_EQUAL(handler.size(), 5u); 
-	BOOST_CHECK_EQUAL(handler.get_plugin_names(), "absdiff add div mul sub ");
-}
+	struct jpeg_compress_struct info; 
+	struct jpeg_error_mgr       err; 
+};
+
+}; 
diff --git a/addons/jpg/jpg-gray.cc b/addons/jpg/jpg-gray.cc
index 1e93d60..d9b97fe 100644
--- a/addons/jpg/jpg-gray.cc
+++ b/addons/jpg/jpg-gray.cc
@@ -20,7 +20,7 @@
 
 #include <cstdio>
 #include <cstdlib>
-#include <jpeglib.h>
+
 #include <sstream>
 #include <cassert>
 #include <mia/core/file.hh>
@@ -28,6 +28,11 @@
 #include <mia/core/msgstream.hh>
 #include <mia/2d/imageio.hh>
 
+#include "jpeg-common.hh"
+
+
+
+
 NS_BEGIN(IMAGEIO_2D_JPG)
 
 using namespace mia;
@@ -56,9 +61,14 @@ CJpeg2DImageIOPlugin::CJpeg2DImageIOPlugin():
 
 }
 
-METHODDEF(void) mia_jpeg_error_exit (j_common_ptr /*cinfo*/)
+METHODDEF(void) mia_jpeg_load_error_exit (j_common_ptr /*cinfo*/)
+{
+	throw mia::create_exception<runtime_error>("JpegGray::load: error reading from input file"); 
+}
+
+METHODDEF(void) mia_jpeg_save_error_exit (j_common_ptr /*cinfo*/)
 {
-	throw create_exception<runtime_error>("Jpeg::load: error reading from input file"); 
+	throw create_exception<runtime_error>("JpegGray::save: error reading from input file"); 
 }
 
 
@@ -66,55 +76,45 @@ C2DImageIOPlugin::PData CJpeg2DImageIOPlugin::do_load(const string& fname) const
 {
 	CInputFile f(fname);
 	if (!f)
-		throw create_exception<runtime_error>("CPNG2DImageIO::save:unable to open input file '", fname, "'");
+		throw create_exception<runtime_error>("C2DImageIOPlugin::load :unable to open input file '", fname, "'");
 
-	struct jpeg_decompress_struct cdecompress_info;
-	struct jpeg_error_mgr jerr;
-	
-	cdecompress_info.err = jpeg_std_error(&jerr);
+	miajpeg::JpegDecompress decompress; 
+	decompress.err.error_exit = mia_jpeg_load_error_exit;
 
-	jerr.error_exit = mia_jpeg_error_exit;
- 
-	jpeg_create_decompress(&cdecompress_info);
-	
-	jpeg_stdio_src(&cdecompress_info, f);
+	jpeg_stdio_src(&decompress.info, f);
 	
 	// is it a jpeg image? 
-	if (jpeg_read_header(&cdecompress_info, TRUE) != JPEG_HEADER_OK) 
+	if (jpeg_read_header(&decompress.info, TRUE) != JPEG_HEADER_OK) 
 		return C2DImageIOPlugin::PData(); 
 
-	(void) jpeg_start_decompress(&cdecompress_info);
+	jpeg_start_decompress(&decompress.info);
 	// only one component? 
-	if (cdecompress_info.output_components != 1) {
-		jpeg_destroy_decompress(&cdecompress_info);
+	if (decompress.info.output_components != 1) {
 		throw create_exception<runtime_error>(":MIA only supports gray scale images, but got an image with ", 
-					    cdecompress_info.output_components, " color components.");
+					    decompress.info.output_components, " color components.");
 	}
 
-	if (cdecompress_info.data_precision != 8) {
-		jpeg_destroy_decompress(&cdecompress_info);
+	if (decompress.info.data_precision != 8) {
 		throw create_exception<runtime_error>(":MIA only supports 8-bit per pixel images, but got an image with ", 
-						      cdecompress_info.data_precision, " bits data precision.");
+						      decompress.info.data_precision, " bits data precision.");
 	}
 
-
-	int row_stride = cdecompress_info.output_width * cdecompress_info.output_components;
+	int row_stride = decompress.info.output_width * decompress.info.output_components;
 	vector<JSAMPLE> buf(row_stride); 
 	
 	JSAMPROW buffer[1]; 
 	buffer[0] = &buf[0]; 
 
-	C2DUBImage *result = new C2DUBImage(C2DBounds(cdecompress_info.output_width, cdecompress_info.output_height)); 
+	C2DUBImage *result = new C2DUBImage(C2DBounds(decompress.info.output_width, decompress.info.output_height)); 
 	P2DImage presult(result); 
 	
-	while (cdecompress_info.output_scanline < cdecompress_info.output_height) {
-		(void) jpeg_read_scanlines(&cdecompress_info, buffer, 1);
+	while (decompress.info.output_scanline < decompress.info.output_height) {
+		(void) jpeg_read_scanlines(&decompress.info, buffer, 1);
 		copy(buf.begin(), buf.end(), 
-		     result->begin_at(0, cdecompress_info.output_scanline - 1)); 
+		     result->begin_at(0, decompress.info.output_scanline - 1)); 
 	}
 	
-	jpeg_destroy_decompress(&cdecompress_info);
-	
+
 	C2DImageIOPlugin::PData result_vector(new C2DImageIOPlugin::Data); 
 	result_vector->push_back(presult); 
 	return result_vector; 
@@ -123,34 +123,34 @@ C2DImageIOPlugin::PData CJpeg2DImageIOPlugin::do_load(const string& fname) const
 bool CJpeg2DImageIOPlugin::do_save_jpeg(FILE *f, const C2DUBImage& image) const 
 {
 
-	struct jpeg_compress_struct cinfo; 
-	struct jpeg_error_mgr       jerr; 
+	miajpeg::JpegCompress compress; 
+
+	jpeg_create_compress(&compress.info);
+	compress.err.error_exit = mia_jpeg_save_error_exit;
 
-	cinfo.err = jpeg_std_error(&jerr);
-	jpeg_create_compress(&cinfo);
 	
-	cinfo.image_width = image.get_size().x; 
-	cinfo.image_height = image.get_size().y; 
+	compress.info.image_width = image.get_size().x; 
+	compress.info.image_height = image.get_size().y; 
 	
 	vector<JSAMPLE> samples(image.get_size().x); 
 	JSAMPROW scanline[1]; 
 	scanline[0] = &samples[0]; 
 
-	cinfo.input_components = 1;
-	cinfo.in_color_space = JCS_GRAYSCALE; 
+	compress.info.input_components = 1;
+	compress.info.in_color_space = JCS_GRAYSCALE; 
 
-	jpeg_set_defaults(&cinfo);
-	jpeg_set_quality(&cinfo,100,1);
+	jpeg_set_defaults(&compress.info);
+	jpeg_set_quality(&compress.info,100,1);
 
-	jpeg_stdio_dest(&cinfo,f);
-	jpeg_start_compress(&cinfo,TRUE);
+	jpeg_stdio_dest(&compress.info,f);
+	jpeg_start_compress(&compress.info,TRUE);
 	
 	for (unsigned int y = 0; y < image.get_size().y; ++y) {
-		copy(image.begin_at(0,y), image.begin_at(0,y) + cinfo.image_width, scanline[0]); 
-		jpeg_write_scanlines(&cinfo,scanline,1); 
+		copy(image.begin_at(0,y), image.begin_at(0,y) + compress.info.image_width, scanline[0]); 
+		jpeg_write_scanlines(&compress.info,scanline,1); 
 	}
-	jpeg_finish_compress(&cinfo);
-	jpeg_destroy_compress(&cinfo);
+	jpeg_finish_compress(&compress.info);
+	jpeg_destroy_compress(&compress.info);
 	return true; 
 }
 
diff --git a/addons/jpg/jpg-rgb.cc b/addons/jpg/jpg-rgb.cc
index 9efae2a..2d9306e 100644
--- a/addons/jpg/jpg-rgb.cc
+++ b/addons/jpg/jpg-rgb.cc
@@ -20,7 +20,6 @@
 
 #include <cstdio>
 #include <cstdlib>
-#include <jpeglib.h>
 #include <sstream>
 #include <cassert>
 #include <mia/core/file.hh>
@@ -28,6 +27,8 @@
 #include <mia/core/msgstream.hh>
 #include <mia/2d/rgbimageio.hh>
 
+#include "jpeg-common.hh"
+
 NS_BEGIN(RGBIMAGEIO_2D_JPG)
 
 using namespace mia;
@@ -55,9 +56,14 @@ CJpegRGB2DImageIOPlugin::CJpegRGB2DImageIOPlugin():
 	add_suffix(".JPEG");
 }
 
-METHODDEF(void) mia_jpeg_error_exit (j_common_ptr /*cinfo*/)
+METHODDEF(void) mia_jpeg_load_error_exit (j_common_ptr /*cinfo*/)
+{
+	throw create_exception<runtime_error>("JpegRGB::load: error reading from input file"); 
+}
+
+METHODDEF(void) mia_jpeg_save_error_exit (j_common_ptr /*cinfo*/)
 {
-	throw create_exception<runtime_error>("Jpeg::load: error reading from input file"); 
+	throw create_exception<runtime_error>("JpegRGB::save: error reading from input file"); 
 }
 
 
@@ -66,83 +72,73 @@ C2DRGBImageIOPlugin::PData CJpegRGB2DImageIOPlugin::do_load(const string& fname)
 
 	CInputFile f(fname);
 	if (!f)
-		throw create_exception<runtime_error>("CPNG2DImageIO::save:unable to open input file '", fname, "'");
-
-	struct jpeg_decompress_struct cdecompress_info;
-	struct jpeg_error_mgr jerr;
-	
-	cdecompress_info.err = jpeg_std_error(&jerr);
+		throw create_exception<runtime_error>("CJpegRGB2DImageIO::save:unable to open input file '", fname, "'");
 
-	jerr.error_exit = mia_jpeg_error_exit;
- 
-	jpeg_create_decompress(&cdecompress_info);
+	miajpeg::JpegDecompress decompress; 
+	decompress.err.error_exit = mia_jpeg_load_error_exit;
 	
-	jpeg_stdio_src(&cdecompress_info, f);
+	jpeg_stdio_src(&decompress.info, f);
 	
 	// is it a jpeg image? 
-	if (jpeg_read_header(&cdecompress_info, TRUE) != JPEG_HEADER_OK) 
+	if (jpeg_read_header(&decompress.info, TRUE) != JPEG_HEADER_OK) 
 		return C2DRGBImageIOPlugin::PData(); 
 
-	(void) jpeg_start_decompress(&cdecompress_info);
+	jpeg_start_decompress(&decompress.info);
 	// only one component? 
-	if (cdecompress_info.output_components != 3) {
-		jpeg_destroy_decompress(&cdecompress_info);
+	if (decompress.info.output_components != 3) {
 		throw create_exception<runtime_error>(":MIA this plugin only supports RGB images, but got an image with ", 
-					    cdecompress_info.output_components, " color components.");
+					    decompress.info.output_components, " color components.");
 	}
 
 
-	int row_stride = cdecompress_info.output_width * cdecompress_info.output_components * 3;
+	int row_stride = decompress.info.output_width * decompress.info.output_components * 3;
 	vector<JSAMPLE> buf(row_stride); 
 	
 	JSAMPROW buffer[1]; 
 	buffer[0] = &buf[0]; 
 
-	CRGB2DImage *result = new CRGB2DImage(C2DBounds(cdecompress_info.output_width, cdecompress_info.output_height)); 
+	CRGB2DImage *result = new CRGB2DImage(C2DBounds(decompress.info.output_width, decompress.info.output_height)); 
 	PRGB2DImage presult(result); 
 	
-	while (cdecompress_info.output_scanline < cdecompress_info.output_height) {
-		(void) jpeg_read_scanlines(&cdecompress_info, buffer, 1);
+	while (decompress.info.output_scanline < decompress.info.output_height) {
+		(void) jpeg_read_scanlines(&decompress.info, buffer, 1);
 		copy(buf.begin(), buf.end(), 
-		     result->pixel() + ((cdecompress_info.output_scanline - 1) * row_stride));  
+		     result->pixel() + ((decompress.info.output_scanline - 1) * row_stride));  
 	}
 	
-	jpeg_destroy_decompress(&cdecompress_info);
 	return presult; 
 }
 
 bool CJpegRGB2DImageIOPlugin::do_save_jpeg(FILE *f, const CRGB2DImage& image) const 
 {
 
-	struct jpeg_compress_struct cinfo; 
-	struct jpeg_error_mgr       jerr; 
+	miajpeg::JpegCompress compress; 
 
-	cinfo.err = jpeg_std_error(&jerr);
-	jpeg_create_compress(&cinfo);
+	jpeg_create_compress(&compress.info);
+	compress.err.error_exit = mia_jpeg_save_error_exit;
 	
-	cinfo.image_width = image.get_size().x; 
-	cinfo.image_height = image.get_size().y; 
+	compress.info.image_width = image.get_size().x; 
+	compress.info.image_height = image.get_size().y; 
 	
 	vector<JSAMPLE> samples(image.get_size().x * 3); 
 	JSAMPROW scanline[1]; 
 	scanline[0] = &samples[0]; 
 
-	cinfo.input_components = 3;
-	cinfo.in_color_space = JCS_RGB; 
+	compress.info.input_components = 3;
+	compress.info.in_color_space = JCS_RGB; 
 
-	jpeg_set_defaults(&cinfo);
-	jpeg_set_quality(&cinfo,80,1);
+	jpeg_set_defaults(&compress.info);
+	jpeg_set_quality(&compress.info,80,1);
 
-	jpeg_stdio_dest(&cinfo,f);
-	jpeg_start_compress(&cinfo,TRUE);
+	jpeg_stdio_dest(&compress.info,f);
+	jpeg_start_compress(&compress.info,TRUE);
 	int dx = image.get_size().x * 3; 
 
 	for (unsigned int y = 0; y < image.get_size().y; ++y) {
 		copy(image.pixel() + y * dx, image.pixel() + (y + 1) * dx, scanline[0]); 
-		jpeg_write_scanlines(&cinfo,scanline,1); 
+		jpeg_write_scanlines(&compress.info,scanline,1); 
 	}
-	jpeg_finish_compress(&cinfo);
-	jpeg_destroy_compress(&cinfo);
+	jpeg_finish_compress(&compress.info);
 	return true; 
 }
 
diff --git a/addons/nifti/niftiimage.cc b/addons/nifti/niftiimage.cc
index 80d0766..d908d3a 100644
--- a/addons/nifti/niftiimage.cc
+++ b/addons/nifti/niftiimage.cc
@@ -86,6 +86,8 @@ struct NiftiDeallocator {
 void copy_attributes(C3DImage& image, const nifti_image& ni)
 {
         // set position and orientation 
+	image.set_attribute(AttrID_nifti_qform_code, ni.qform_code);
+	
         if (ni.qform_code == 0) { // method 1
                 image.set_orientation(ior_default);
                 image.set_voxel_size(C3DFVector(ni.dx,  ni.dy, ni.dz)); 
@@ -97,7 +99,6 @@ void copy_attributes(C3DImage& image, const nifti_image& ni)
                                         ni.quatern_c * ni.quatern_c + 
                                         ni.quatern_d * ni.quatern_d)); 
                 image.set_rotation(Quaternion(qa, ni.quatern_b, ni.quatern_c, ni.quatern_d));
-                image.set_attribute(AttrID_nifti_qform_code, ni.qform_code); 
         }
         
         if (ni.sform_code > 0) { // method 3
@@ -342,29 +343,42 @@ bool CNifti3DImageIOPlugin::do_save(const std::string& fname, const Data& data)
 	// need to see whether to support this 
 	output->cal_min = 0.0f;
 	output->cal_max = 0.0f ;
-	
-	// here starts the orientation insanity 
-	// todo: re-check how this qfac is actually used
-	output->qfac = 1; 
-	switch (image.get_orientation()) {
-		// Coverty complains here. 
-		// flipped needs to sent an extra parameter and 
-		// then fall through to the next case 
-	case ior_xyz_flipped: output->qfac = -1; 
-	case ior_undefined:
-	case ior_xyz: {
-		output->qform_code = 1; 
+
+	if (image.has_attribute(AttrID_nifti_qform_code)) {
+		output->qform_code = image.get_attribute_as<int>(AttrID_nifti_qform_code); 
+	} else {
+		output->qform_code = 0; // default to method 2 
+	}
+
+	// Analyze 7.5 like data 
+	if (output->qform_code == 0) {
+		// here starts the orientation insanity 
+		// todo: re-check how this qfac is actually used
+
+		auto org = image.get_origin(); 
+		output->qoffset_x = org.x; 
+		output->qoffset_y = org.y; 
+		output->qoffset_z = org.z; 
+		output->quatern_b = 0.0; 
+		output->quatern_c = 0.0; 
+		output->quatern_d = 0.0;
+		
+		switch (image.get_orientation()) {
+		case ior_undefined:
+		case ior_xyz: break; 
+		default: 
+			cvwarn() << __FUNCTION__ << "FIXME:manual set orientation detected, but ignored\n"; 
+		}
+	} else {
+		output->qfac = (image.get_orientation() == ior_xyz_flipped) ? -1 : 1; 
 		auto org = image.get_origin(); 
 		output->qoffset_x = org.x; 
 		output->qoffset_y = org.y; 
 		output->qoffset_z = org.z; 
-		auto rot = image.get_rotation().as_quaternion();
+		auto rot = image.get_rotation().as_quaternion(); 
 		output->quatern_b = rot.x(); 
 		output->quatern_c = rot.y(); 
 		output->quatern_d = rot.z();
-	} break; 
-	default: 
-		cvwarn() << __FUNCTION__ << "FIXME:manual set orientation detected, but ignored\n";  
 	}
 	
 	// copy s-form if available 
@@ -398,9 +412,9 @@ bool CNifti3DImageIOPlugin::do_save(const std::string& fname, const Data& data)
 	output->time_units = image.get_attribute_as<int>(AttrID_nifti_time_units, NIFTI_UNITS_SEC);
 
 	output->intent_code = image.get_attribute_as<int>(AttrID_nifti_intent_code, 0);
-	output->intent_p1 = image.get_attribute_as<int>(AttrID_nifti_intent_p1, 0);
-	output->intent_p2 = image.get_attribute_as<int>(AttrID_nifti_intent_p2, 0);
-	output->intent_p3 = image.get_attribute_as<int>(AttrID_nifti_intent_p3, 0);
+	output->intent_p1 = image.get_attribute_as<float>(AttrID_nifti_intent_p1, 0);
+	output->intent_p2 = image.get_attribute_as<float>(AttrID_nifti_intent_p2, 0);
+	output->intent_p3 = image.get_attribute_as<float>(AttrID_nifti_intent_p3, 0);
 	string intent_name = image.get_attribute_as<string>(AttrID_nifti_intent_name, ""); 
 	if (!intent_name.empty()) {
 		strncpy(output->intent_name, intent_name.c_str(),  14);
diff --git a/addons/nifti/test_niftiimage.cc b/addons/nifti/test_niftiimage.cc
index a427453..6a2ed1d 100644
--- a/addons/nifti/test_niftiimage.cc
+++ b/addons/nifti/test_niftiimage.cc
@@ -67,6 +67,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( test_simple_write_read, T, type )
 	pimage->set_voxel_size(voxel); 
 	pimage->set_origin(origin); 
         pimage->set_rotation(rot); 
+	pimage->set_attribute("nifti-qform-code", 1);
 
 	CNifti3DImageIOPlugin io; 
         CNifti3DImageIOPlugin::Data images;
diff --git a/cmake/macros.cmake b/cmake/macros.cmake
index 8c495d7..907a644 100644
--- a/cmake/macros.cmake
+++ b/cmake/macros.cmake
@@ -120,30 +120,70 @@ MACRO(ASSERT_SIZE  NAME EXPECTED)
   ENDIF(NOT ${${NAME}_TYPE_SIZE} EQUAL ${EXPECTED})
 ENDMACRO(ASSERT_SIZE)
 
-MACRO(CREATE_EXE_DOCU name) 
-  
+
+
+#
+# This macro runs the program to create the XMLprogram descrition 
+# that is used to create documentation and interfaced 
+#
+MACRO(CREATE_EXE_XML_HELP name)
   ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_BINARY_DIR}/doc/mia-${name}.xml
     COMMAND MIA_PLUGIN_TESTPATH=${PLUGIN_TEST_ROOT}/${PLUGIN_INSTALL_PATH} 
     ./mia-${name} --help-xml ${CMAKE_BINARY_DIR}/doc/mia-${name}.xml
     COMMAND rm -f ${CMAKE_SOURCE_DIR}/doc/userref.stamp
-    DEPENDS mia-${name} plugin_test_links )
+    DEPENDS mia-${name} )
     
   ADD_CUSTOM_TARGET(mia-${name}-xml DEPENDS ${CMAKE_BINARY_DIR}/doc/mia-${name}.xml)
   ADD_DEPENDENCIES(XMLDOC mia-${name}-xml)
-  
-  SET(${name}-manfile ${CMAKE_BINARY_DIR}/doc/man/mia-${name}.1)
-  
-  ADD_CUSTOM_COMMAND(OUTPUT   ${${name}-manfile}
-    COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_SOURCE_DIR}/doc/miaxml2man.py 
-    ${CMAKE_BINARY_DIR}/doc/mia-${name}.xml >${${name}-manfile}
-    MAIN_DEPENDENCY ${CMAKE_BINARY_DIR}/doc/mia-${name}.xml
-    DEPENDS mandir mia-${name}-xml
-    )
-  ADD_CUSTOM_TARGET(mia-${name}-man DEPENDS ${${name}-manfile})
-  add_dependencies(manpages mia-${name}-man)    
-ENDMACRO(CREATE_EXE_DOCU)
+ENDMACRO(CREATE_EXE_XML_HELP)
+
+
+MACRO(CREATE_NIPYPE_FROM_XML name)
+  IF(CREATE_NIPYPE_INTERFACES)
+    STRING(REPLACE "-" "_" PythonName ${name})
+
+    SET(${name}-nipype-interface ${CMAKE_CURRENT_BINARY_DIR}/mia_${PythonName}.py)
+    
+    ADD_CUSTOM_COMMAND(OUTPUT ${${name}-nipype-interface} 
+      COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_SOURCE_DIR}/doc/miaxml2nipype.py 
+      -i ${CMAKE_BINARY_DIR}/doc/mia-${name}.xml -o ${${name}-nipype-interface}
+      MAIN_DEPENDENCY ${CMAKE_BINARY_DIR}/doc/mia-${name}.xml)
+    
+    ADD_CUSTOM_TARGET(mia-${name}-nipype DEPENDS ${${name}-nipype-interface})
+    ADD_DEPENDENCIES(nipypeinterfaces mia-${name}-nipype)
+    
+    INSTALL(FILES ${${name}-nipype-interface} DESTINATION ${NIPYPE_INTERFACE_DIR}/mia)
+
+  ENDIF(CREATE_NIPYPE_INTERFACES)
+ENDMACRO(CREATE_NIPYPE_FROM_XML)
+#
+#
+# man pages can only be created if the python + lxml packages are available 
+#
+MACRO(CREATE_MANPAGE_FROM_XML name)
+  IF(CREATE_USERDOC) 
+    
+    SET(${name}-manfile ${CMAKE_BINARY_DIR}/doc/man/mia-${name}.1)
+    
+    ADD_CUSTOM_COMMAND(OUTPUT   ${${name}-manfile}
+      COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_SOURCE_DIR}/doc/miaxml2man.py 
+      ${CMAKE_BINARY_DIR}/doc/mia-${name}.xml >${${name}-manfile}
+      MAIN_DEPENDENCY ${CMAKE_BINARY_DIR}/doc/mia-${name}.xml
+      DEPENDS mandir mia-${name}-xml
+      )
+    ADD_CUSTOM_TARGET(mia-${name}-man DEPENDS ${${name}-manfile})
+    add_dependencies(manpages mia-${name}-man)    
+  ENDIF(CREATE_USERDOC)
+
+ENDMACRO(CREATE_MANPAGE_FROM_XML)
 
 
+#MACRO(MIA_EXE_CREATE_DOCU_AND_INTERFACE name)
+#  CREATE_EXE_XML_HELP(${name})
+#  CREATE_MANPAGE_FROM_XML(${name})
+#  CREATE_NIPYPE_FROM_XML(${name})
+# ENDMACRO(MIA_EXE_CREATE_DOCU_AND_INTERFACE)
+
 MACRO(DEFEXE name libraries) 
   ADD_EXECUTABLE(mia-${name} ${name}.cc)
   FOREACH(lib ${libraries}) 
@@ -152,20 +192,25 @@ MACRO(DEFEXE name libraries)
   
   TARGET_LINK_LIBRARIES(mia-${name} ${BASELIBS})
   INSTALL(TARGETS mia-${name} RUNTIME DESTINATION "bin")
-  CREATE_EXE_DOCU(${name})
+  ADD_DEPENDENCIES(mia-${name} plugin_test_links)
+  MIA_EXE_CREATE_DOCU_AND_INTERFACE(mia ${name})
 ENDMACRO(DEFEXE)
 
+
 MACRO(DEFCHKEXE name deps) 
-   ADD_EXECUTABLE(mia-${name} ${name}.cc)
-   
-   FOREACH(lib ${deps}) 
-       TARGET_LINK_LIBRARIES(mia-${name} ${lib})
-   ENDFOREACH(lib)
-   SET_TARGET_PROPERTIES(mia-${name} PROPERTIES COMPILE_FLAGS -DVSTREAM='\\\"TEST-2D\\\"' COMPILE_FLAGS -DBOOST_TEST_DYN_LINK)
-   TARGET_LINK_LIBRARIES(mia-${name} ${BASELIBS})
-   TARGET_LINK_LIBRARIES(mia-${name} ${BOOST_UNITTEST})
-   INSTALL(TARGETS mia-${name} RUNTIME DESTINATION "bin")
-   CREATE_EXE_DOCU(${name})
+  ADD_EXECUTABLE(mia-${name} ${name}.cc)
+  
+  FOREACH(lib ${deps}) 
+    TARGET_LINK_LIBRARIES(mia-${name} ${lib})
+  ENDFOREACH(lib)
+  SET_TARGET_PROPERTIES(mia-${name} PROPERTIES COMPILE_FLAGS -DVSTREAM='\\\"TEST-2D\\\"' COMPILE_FLAGS -DBOOST_TEST_DYN_LINK)
+  TARGET_LINK_LIBRARIES(mia-${name} ${BASELIBS})
+  TARGET_LINK_LIBRARIES(mia-${name} ${BOOST_UNITTEST})
+  INSTALL(TARGETS mia-${name} RUNTIME DESTINATION "bin")
+
+  MIA_EXE_CREATE_DOCU_AND_INTERFACE(mia ${name})
+  ADD_DEPENDENCIES(mia-${name} plugin_test_links)
+  ADD_TEST(${name} mia-${name} --selftest)
 ENDMACRO(DEFCHKEXE)
 
 
@@ -177,5 +222,6 @@ MACRO(NEW_TEST name libs)
   IF (NOT WIN32) 
     TARGET_LINK_LIBRARIES(${EXENAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
   ENDIF (NOT WIN32)
+  ADD_DEPENDENCIES(${EXENAME} plugin_test_links)
   ADD_TEST(${name} ${EXENAME})
 ENDMACRO(NEW_TEST)
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 8df7b73..3f7cd58 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -19,18 +19,32 @@
 
 INCLUDE (${CMAKE_ROOT}/Modules/FindDoxygen.cmake)
 
+
 ADD_CUSTOM_TARGET(docs echo "creating documentation")
 add_dependencies(doc docs)  
 
-IF(CREATE_USERDOC) 
+SET(MIADOCTOOLS_FILES 
+  miareadxml.py  
+  miawritprogram.py  
+  MiaDoctools.cmake
+  __init__.py
+  )
 
-  add_dependencies(docs manpages)    
-  IF(ALWAYS_CREATE_DOC) 
-    INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man/ DESTINATION share/man/man1/)
-  ENDIF(ALWAYS_CREATE_DOC) 
+SET(MIADOCTOOLS_PYTHON_EXE
+  miaxml2man.py  
+  miaxml2nipype.py  
+  miaxml2sgml.py
+  )
+
+INSTALL(FILES ${MIADOCTOOLS_FILES} DESTINATION ${MIA_DOCTOOLS_INSTALL_ROOT})
+
+INSTALL(PROGRAMS ${MIADOCTOOLS_PYTHON_EXE} DESTINATION ${MIA_DOCTOOLS_INSTALL_ROOT})
+
+
+IF(CREATE_USERDOC) 
 
   ##################################################################
-  #  for html userref xsltproc and the style sheet is needed 
+  #  for html userref xsltproc and the style sheet is needed
   #
   find_program(XSLTPROC xsltproc)
   IF(XSLTPROC)
@@ -59,6 +73,14 @@ IF(CREATE_USERDOC)
       COMMAND ln ARGS -sf ${CMAKE_CURRENT_SOURCE_DIR}/progref.xml ${CMAKE_CURRENT_BINARY_DIR}/progref.xml) 
 
     ADD_CUSTOM_TARGET(progref_link DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/progref.xml)
+
+    ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/program.xml 
+      COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/miaxml2sgml.py ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
+      DEPENDS xmldoc
+      )
+    
+    ADD_CUSTOM_TARGET(process_xml DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/program.xml)
+
       
     ADD_CUSTOM_COMMAND(OUTPUT  "userref.stamp"
       COMMAND  
@@ -70,10 +92,10 @@ IF(CREATE_USERDOC)
       --output "userref/" 
       ${HTML_CHUNK_FILEPATH}/chunk.xsl progref.xml
       COMMAND touch ARGS userref.stamp
-      DEPENDS process_xml userref_css userref_outdir progref_link ${CMAKE_CURRENT_BINARY_DIR}/program.xml
-      ) 
+      DEPENDS process_xml userref_css userref_outdir progref_link ${CMAKE_CURRENT_BINARY_DIR}/program.xml ) 
+    
     ADD_CUSTOM_TARGET(userref DEPENDS userref.stamp)
-    add_dependencies(docs userref)  
+    add_dependencies(docs userref)
     
     ####################################################
     #
@@ -85,7 +107,7 @@ IF(CREATE_USERDOC)
     ENDIF(ALWAYS_CREATE_DOC)     
   ENDIF(HTML_CHUNK_FILEPATH) 
   
-ENDIF(CREATE_USERDOC) 
+ENDIF(CREATE_USERDOC)
 
 IF (DOXYGEN_FOUND)
   ADD_CUSTOM_TARGET(LibraryDoc echo "creating user library documentation")
diff --git a/doc/MiaDoctools.cmake b/doc/MiaDoctools.cmake
new file mode 100644
index 0000000..b9e4ca1
--- /dev/null
+++ b/doc/MiaDoctools.cmake
@@ -0,0 +1,187 @@
+#
+# This file is part of MIA - a toolbox for medical image analysis 
+# Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+#
+# MIA is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+
+
+#
+# This macro is used to prepare the creation of the man pages and 
+# interfaces 
+# - prefix will be used to set the prefix of the executables and the 
+# target directory of the nipype interface 
+#
+MACRO(MIA_PREPARE_AUTODOC prefix)
+
+  IF(NOT MIA_DOCTOOLS_ROOT)
+    SET(MIA_DOCTOOLS_ROOT "${CMAKE_SOURCE_DIR}/doc")
+  ENDIF(NOT MIA_DOCTOOLS_ROOT)
+  
+  OPTION(MIA_CREATE_MANPAGES "Create the man pages for the executables (Required Python and python-lxml)" OFF)
+  OPTION(MIA_CREATE_NIPYPE_INTERFACES "Create the nipype interfaces for the executables (Required Python,python-lxml, and nipype)" OFF)
+  
+  IF(MIA_CREATE_MANPAGES OR MIA_CREATE_NIPYPE)
+    
+    FIND_PACKAGE(PythonInterp REQUIRED)
+    EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c "import lxml"  RESULT_VARIABLE LXML_ERR)
+    IF(LXML_ERR) 
+      MESSAGE(FATAL "Python found, but no pythonl-xml")
+    ENDIF(LXML_ERR)
+    
+    IF(MIA_CREATE_MANPAGES) 
+      ADD_CUSTOM_TARGET(manpages ALL)
+    ENDIF()
+    
+    IF(MIA_CREATE_NIPYPE_INTERFACES)
+      file(WRITE ${NIPYPE_INTERFACE_INIT_FILE} "# Automatically generated file, do not edit\n")
+
+      STRING(COMPARE EQUAL "${CMAKE_INSTALL_PREFIX}" "/usr" INSTALLROOT_IS_USER)
+      
+      IF(INSTALLROOT_IS_USER)
+	EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib\nimport sys\nsys.stdout.write(get_python_lib())"
+	  RESULT_VARIABLE SITEPACKGE_ERR
+	  OUTPUT_VARIABLE SITEPACKGE_BASE_PATH)
+      ELSE()
+	EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c "import site\nimport sys\nsys.stdout.write(site.getusersitepackages())"
+	  RESULT_VARIABLE SITEPACKGE_ERR
+	  OUTPUT_VARIABLE SITEPACKGE_BASE_PATH)
+      ENDIF()
+
+      IF(SITEPACKGE_ERR) 
+        MESSAGE(FATAL "Something went wrong identifying the nipype installation loaction") 
+      ENDIF()
+
+      SET(NIPYPE_INTERFACE_DIR "${SITEPACKGE_BASE_PATH}/${prefix}/nipype/interfaces/")
+      
+      
+      
+      MESSAGE(STATUS "Will create nipype interfaces and install to " ${NIPYPE_INTERFACE_DIR}) 
+      
+      ADD_CUSTOM_TARGET(nipypeinterfaces ALL)
+      INSTALL(FILES ${NIPYPE_INTERFACE_INIT_FILE} DESTINATION ${NIPYPE_INTERFACE_DIR})
+    ENDIF()
+  ENDIF()
+
+  # install empty init files 
+  INSTALL(FILES ${MIA_DOCTOOLS_ROOT}/__init__.py DESTINATION ${SITEPACKGE_BASE_PATH}/${prefix})
+  INSTALL(FILES ${MIA_DOCTOOLS_ROOT}/__init__.py DESTINATION ${SITEPACKGE_BASE_PATH}/${prefix}/nipype)
+  
+ENDMACRO(MIA_PREPARE_AUTODOC) 
+
+
+#
+# INTERNAL USE 
+# This macro runs the program to create the XML program descrition 
+# that is used to create documentation and interfaced 
+# TODO: add possible plug-ins that come directly from the software package 
+#
+MACRO(MIA_CREATE_EXE_XML_HELP prefix name)
+  ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_BINARY_DIR}/doc/${prefix}-${name}.xml
+    COMMAND MIA_PLUGIN_TESTPATH=${PLUGIN_TEST_ROOT}/${PLUGIN_INSTALL_PATH} ./${prefix}-${name} --help-xml ${CMAKE_BINARY_DIR}/doc/${prefix}-${name}.xml
+    DEPENDS ${prefix}-${name})
+    
+  ADD_CUSTOM_TARGET(${prefix}-${name}-xml DEPENDS ${CMAKE_BINARY_DIR}/doc/${prefix}-${name}.xml)
+  ADD_DEPENDENCIES(xmldoc ${prefix}-${name}-xml)
+ENDMACRO(MIA_CREATE_EXE_XML_HELP)
+
+#
+# INTERNAL USE 
+# Create the nipype interface from the xml doc description 
+# and add it to the install target 
+#
+
+MACRO(MIA_CREATE_NIPYPE_FROM_XML prefix name)
+  STRING(REPLACE "-" "_" PythonName ${name})
+  
+  SET(${prefix}-${name}-nipype-interface ${CMAKE_CURRENT_BINARY_DIR}/${prefix}_${PythonName}.py)
+  
+  ADD_CUSTOM_COMMAND(OUTPUT ${${prefix}-${name}-nipype-interface} 
+    COMMAND ${PYTHON_EXECUTABLE} ${MIA_DOCTOOLS_ROOT}/miaxml2nipype.py -i ${CMAKE_BINARY_DIR}/doc/${prefix}-${name}.xml -o ${${prefix}-${name}-nipype-interface}
+    MAIN_DEPENDENCY ${CMAKE_BINARY_DIR}/doc/${prefix}-${name}.xml)
+
+  FILE(APPEND ${NIPYPE_INTERFACE_INIT_FILE} "from .${prefix}_${PythonName} import ${prefix}_${PythonName}\n")
+  
+  ADD_CUSTOM_TARGET(${prefix}-${name}-nipype DEPENDS ${${prefix}-${name}-nipype-interface})
+  ADD_DEPENDENCIES(nipypeinterfaces ${prefix}-${name}-nipype)
+  
+  INSTALL(FILES ${${prefix}-${name}-nipype-interface} DESTINATION ${NIPYPE_INTERFACE_DIR})
+ENDMACRO(MIA_CREATE_NIPYPE_FROM_XML)
+
+#
+# INTERNAL USE 
+# Create the man page from the xml doc description 
+# and add it to the install target 
+#
+MACRO(MIA_CREATE_MANPAGE_FROM_XML prefix name)
+  SET(${prefix}-${name}-manfile ${CMAKE_CURRENT_BINARY_DIR}/${prefix}-${name}.1)
+  ADD_CUSTOM_COMMAND(OUTPUT   ${${prefix}-${name}-manfile}
+    COMMAND ${PYTHON_EXECUTABLE} ${MIA_DOCTOOLS_ROOT}/miaxml2man.py ${CMAKE_BINARY_DIR}/doc/${prefix}-${name}.xml >${${prefix}-${name}-manfile}
+      MAIN_DEPENDENCY ${CMAKE_BINARY_DIR}/doc/${prefix}-${name}.xml
+      )
+    ADD_CUSTOM_TARGET(${prefix}-${name}-man DEPENDS ${${prefix}-${name}-manfile})
+    add_dependencies(manpages ${prefix}-${name}-man)
+    INSTALL(FILES ${${prefix}-${name}-manfile} DESTINATION "share/man/man1")
+ENDMACRO(MIA_CREATE_MANPAGE_FROM_XML)
+
+
+#
+# INTERNAL USE 
+# Run the necessary steps to create the documentation 
+# and nipype interfaces (if enabled)
+#
+
+MACRO(MIA_EXE_CREATE_DOCU_AND_INTERFACE prefix name)
+  MIA_CREATE_EXE_XML_HELP(${prefix} ${name})
+  
+  IF(MIA_CREATE_MANPAGES) 
+    MIA_CREATE_MANPAGE_FROM_XML(${prefix} ${name})
+  ENDIF(MIA_CREATE_MANPAGES)
+
+  IF(MIA_CREATE_NIPYPE_INTERFACES)
+    MIA_CREATE_NIPYPE_FROM_XML(${prefix} ${name})
+  ENDIF(MIA_CREATE_NIPYPE_INTERFACES)
+  
+ENDMACRO(MIA_EXE_CREATE_DOCU_AND_INTERFACE)
+
+#
+# Create an executable and its documentation and nipype interface 
+# Parameters: 
+#   prefix: napespace prefix of the exe
+#   name:   functional name of the exe 
+#   libraries: libraries to link this exe against 
+#
+MACRO(MIA_DEFEXE prefix name libraries) 
+  ADD_EXECUTABLE(${prefix}-${name} ${name}.cc)
+  TARGET_LINK_LIBRARIES(${prefix}-${name} ${libraries})
+  INSTALL(TARGETS ${prefix}-${name} RUNTIME DESTINATION "bin")
+  MIA_EXE_CREATE_DOCU_AND_INTERFACE(${prefix}  ${name})
+
+ENDMACRO(MIA_DEFEXE)
+
+#
+# Create an executable and its documentation and nipype interface 
+# that also provides a selftest 
+# 
+# Parameters: 
+#   prefix: napespace prefix of the exe
+#   name:   functional name of the exe 
+#   libraries: libraries to link this exe against 
+#
+MACRO(MIA_DEFEXE_WITH_TEST prefix name deps) 
+
+  MIA_DEFEXE(${prefix} ${name} ${deps})
+  ADD_TEST(${name} ${prefix}-${name} --selftest)
+
+ENDMACRO(MIA_DEFEXE_WITH_TEST)
diff --git a/doc/__init__.py b/doc/__init__.py
new file mode 100644
index 0000000..2129291
--- /dev/null
+++ b/doc/__init__.py
@@ -0,0 +1 @@
+# Emty file to ensure python finds the modules 
diff --git a/doc/extract_docu.py b/doc/extract_docu.py
deleted file mode 100644
index e55fcf6..0000000
--- a/doc/extract_docu.py
+++ /dev/null
@@ -1,159 +0,0 @@
-#!/usr/bin/python 
-#
-# Copyright (C) 2011 Gert Wollny <gw.fossdev at gmail.com>
-#  
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-
-import sys
-import re
-import string 
-from fnmatch import fnmatch
-from os.path import walk
-
-
-
-class CPatternCollector:
-   def __init__(self, pattern):
-      self.pattern = pattern
-      self.files=[]
-
-      
-def collect_files(arg, dirname, names):
-    for f in names:
-        if fnmatch(f, arg.pattern):
-            arg.files.append(dirname + "/" + f)
-   
-
-
-def find_files(root, pattern): 
-   arg = CPatternCollector(pattern)
-   walk(root, collect_files, arg)
-   return arg.files 
-
-class DocuSection:
-   def __init__(self):
-      self.body = []
-      self.subsections = {}
-      self.unspecified = []
-      
-   def append_to_body(self, text_block): 
-      self.body.extend(text_block)
-      
-   def append_plugin(self, text_block): 
-      for l in text_block: 
-         e = re.search("subsection\{(.*)\}", l)
-         if e:
-            self.subsections[e.group(1)] = text_block
-            return 
-      self.unspecified.extend(text_block)
-
-   def write(self, output): 
-      for l in self.body:
-         output.write(l)
-      for k in sorted(self.subsections.keys()):
-         sys.stderr.write("  {}\n".format(k))
-         for l in self.subsections[k]:
-            output.write(l)
-
-      for l in self.unspecified:
-         output.write(l)
-    
-
-class DocuCharpter: 
-   def __init__(self):
-      self.sections = {}
-      
-   def add(self, key1, key2, text_block):
-      if not self.sections.has_key(key2):
-         self.sections[key2] = DocuSection()
-
-      if key1 == "Section":
-         self.sections[key2].append_to_body(text_block)
-
-      if key1 == "Description":
-         self.sections[key2].append_plugin(text_block)
-           
-   def write(self, output): 
-      for s in sorted(self.sections.keys()): 
-         sys.stderr.write("{0}\n".format(s))
-         output.write("\\section{{{0}}}".format(s)) 
-         self.sections[s].write(output)
-
-       
-# this will be a list of lists containing all the documentation comment blocks
-comment_blocks = []
-
-
-root= sys.argv[1]
-program_filename = sys.argv[2]
-plugin_filename = sys.argv[3]
-files = find_files(root, "*.cc")
-
-# read all files and extract comment blocks 
-for f in files: 
-
-   # ignore some emacs security copies 
-   h = re.search("/\.#[-a-z0-9]*\.cc", f)
-   if h:
-      continue 
-
-   
-   infile = open(f,"r")
-   lines = infile.readlines()
-
-   current_block = []
-   is_text = False
-   
-   for l in lines: 
-      if is_text: 
-         e = re.search("(?<=LatexEnd)", l)
-         if not e: 
-            current_block.append(l)
-         else:
-            comment_blocks.append(current_block)
-            is_text = False
-      else:
-         m = re.search("LatexBegin", l)
-         if not m: 
-            continue
-         else:
-            current_block = [l]
-            is_text = True
-               
-   if is_text:
-      print "No LatexEnd in {}".format(f)
-      exit(1)
-   infile.close()
-
-
-plugin_sections = DocuCharpter()
-program_sections = DocuCharpter()
-
-for b in comment_blocks: 
-    m = re.search(" *LatexBegin(P[a-z]*)([A-Z][a-z]*){(.*)}", b[0])
-   
-    type_key = m.group(1)
-    if type_key == "Plugin":
-       plugin_sections.add(m.group(2), m.group(3), b[1:])
-    elif type_key == "Program":
-       program_sections.add(m.group(2), m.group(3), b[1:])
-       
-
-
-
-program_file = open(program_filename,"w")
-program_sections.write(program_file)
-
-
-plugin_file = open(plugin_filename,"w")
-plugin_sections.write(plugin_file)
-
diff --git a/doc/mia-xmldoc2man.cmake b/doc/mia-xmldoc2man.cmake
new file mode 100644
index 0000000..0e3712b
--- /dev/null
+++ b/doc/mia-xmldoc2man.cmake
@@ -0,0 +1,5 @@
+#!/bin/sh 
+
+miadoctoolroot=@MIA_DOCTOOLS_ROOT@
+
+$miadoctoolroot/miaxml2man.py $1 >$2
diff --git a/doc/mia-xmldoc2nipype.cmake b/doc/mia-xmldoc2nipype.cmake
new file mode 100644
index 0000000..cf5e14a
--- /dev/null
+++ b/doc/mia-xmldoc2nipype.cmake
@@ -0,0 +1,5 @@
+#!/bin/sh 
+
+miadoctoolroot=@MIA_DOCTOOLS_ROOT@
+
+$miadoctoolroot/miaxml2nipype.py -i $1 -o $2
diff --git a/doc/miareadxml.py b/doc/miareadxml.py
index feef71e..d700bb4 100644
--- a/doc/miareadxml.py
+++ b/doc/miareadxml.py
@@ -27,6 +27,7 @@ xmlns = "{%s}" % xml_namespace
 # supported tags: 
 #   program      main tag 
 #   name         text: program name
+#   version      text: package version number 
 #   section      text: program type
 #   description  text: basic description of the program 
 #   basic_usage  text: generic call 
@@ -83,24 +84,54 @@ class CTextNode:
         if not expect is None and node.tag != expect:
             raise ValueError("expected '%s' got '%s'" % (expect, node.tag))
 
+        self.required = False
+        self.is_input = False
+        self.is_output = False
+        self.no_nipype = False
         self.entry = node.tag
-        self.flags = []
+        self.flags = set()
         self.text  = ""
         if node.text is not None:
             self.text = self.text + node.text
 
         for child in node.iter("flags"):
-            self.flags = self.flags + string.split(child.text)
+            f = string.split(child.text)
+            for ff in f: 
+                self.flags.add(ff) 
             if child.tail is not None:
                 self.text = self.text + child.tail
 
+        for f in self.flags: 
+                p = {
+                    "required": self.set_is_required, 
+                    "input":    self.set_is_input, 
+                    "output":   self.set_is_output,
+                    "nonipype": self.set_nipype_ignore,
+                    }.get(f, self.dummy)(f)
+    
+    def set_is_required(self, f):
+        self.required = True
+
+    def set_is_input(self, f):
+        self.is_input = True
+
+    def set_is_output(self, f):
+        self.is_output = True
+
+    def set_nipype_ignore(self, f):
+        self.no_nipype = True
+
+    def dummy(self, f):
+        warnings.warn ('Unknown flag "{}" encountered'.format(f))
+
+
 class COption(CTextNode):
     def __init__(self, node):
         CTextNode.__init__(self, node, "option")
 
         self.short = node.get("short")
         self.long =  node.get("long")
-        self.required = int(node.get("required")) 
+#        self.required = int(node.get("required")) 
         self.default = node.get("default")
         self.type = node.get("type")
 
@@ -111,9 +142,13 @@ class COption(CTextNode):
             short = "  ";
 
         if len(self.flags) > 0:
-            flagstring = self.flags[0]
-            for f in self.flags[1:]:
-                flagstring = flagstring + ',' + f
+            flagstring = ""
+            for f in self.flags:
+                if f != "nonipype":
+                    if len(flagstring) == 0:
+                        flagstring = f
+                    else:
+                        flagstring = flagstring + ', ' + f
             print ".IP \"%s \-\-%s=(%s)\""% (short, self.long, flagstring)
         else:
             if not self.type == "bool":
@@ -135,9 +170,15 @@ class COption(CTextNode):
         termtext = termtext + "-" + self.long
 
         if len(self.flags) > 0:
-            termtext = termtext + "=(" + self.flags[0]
-            for f in self.flags[1:]:
-                termtext = termtext + ',' + f
+            termtext = termtext + "=("
+            first = True
+            for f in self.flags:
+                if f != "nonipype":
+                    if first: 
+                        termtext = termtext + f
+                        first=False
+                    else:
+                        termtext = termtext + ", " + f
             termtext = termtext + ")"
         elif self.type != "bool":
             termtext = termtext + "="
@@ -164,6 +205,11 @@ class CDictOption(COption):
         for child in node.iter("dict"):
             for v in child:
                 self.dict[v.get("name")] = v.text
+    def get_names_as_string(self):
+        result = ""
+        for k in self.dict.keys():
+            result = result + '"' + k + '", '
+        return result
 
     def do_print_man(self):
         if len(self.dict) > 0:
@@ -182,6 +228,44 @@ class CDictOption(COption):
             parent.append(opttable)
 
 
+class CSetOption(COption):
+    def __init__(self, node):
+        COption.__init__(self, node)
+        self.set = []
+        for child in node.iter("set"):
+            for cc in child.iter("value"):
+                self.set.append(cc.get("name"))
+                
+    def get_names_as_string(self):
+        result = ""
+        for k in self.set:
+            result = result + '"' + k + '", '
+        return result
+
+    def do_print_man(self):
+        if len(self.set) > 0:
+            print ""
+            print ".RS 10"
+            print ".I" 
+
+            print "Supported values are:(", 
+            for k in self.set:
+                print "%s, " % (escape_dash(k)), 
+            print ")"
+            print ".RE"
+
+
+    def do_write_xml(self, parent):
+        if len(self.set) > 0:
+            e = etree.SubElement(parent, "entry", align="left", valign="top")
+            str_list = [" Supported values are:("]
+            
+            for k in self.set:
+                str_list.append("%s, " % (k))
+            str_list.append(")")
+            e.text = ''.join(str_list)
+                
+
 class CIOOption(COption):
     def __init__(self, node):
         COption.__init__(self, node)
@@ -248,6 +332,7 @@ class CGroup:
                     "io": lambda n: CIOOption(n), 
                     "factory": lambda n: CFactoryOption(n), 
                     "dict":    lambda n: CDictOption(n),
+                    "set": lambda n: CSetOption(n),
                     }.get(child.get("type"), lambda n: COption(n))(child)
                 self.options.append(p)
             else:
@@ -266,12 +351,15 @@ class CParam:
         self.name = node.get("name")
         self.type = node.get("type")
         self.default = node.get("default")
-        self.required = int(node.get("required")) 
         self.text = node.text
-        self.flags = []
+        self.required = False
+        self.no_nipype = False 
+        self.flags = set()
 
         for child in node.iter("flags"):
-            self.flags = self.flags + string.split(child.text)
+            f = string.split(child.text)
+            for ff in f: 
+                self.flags.add(ff) 
             if child.tail is not None:
                 self.text = self.text + child.tail
 
@@ -280,13 +368,45 @@ class CParam:
         if m is not None: 
             self.default = "[" + self.default + "]"
 
+        for f in self.flags: 
+                p = {
+                    "required": self.set_is_required, 
+                    "input":    self.set_is_input, 
+                    "output":   self.set_is_output,
+                    "nonipype": self.set_nipype_ignore,
+                    }.get(f, self.dummy)(f)
+    
+    def set_is_required(self, f):
+        self.required = True
+
+    def set_is_input(self, f):
+        self.is_input = True
+
+    def set_is_output(self, f):
+        self.is_output = True
+        
+    def set_nipype_ignore(self, f):
+        self.no_nipype = True
+
+    def dummy(self, f):
+        warnings.warn ('Unknown flag "{}" encountered'.format(f))
+
+
     def print_man(self):
         print ".I"
         print self.name
+
+
         if len(self.flags) > 0:
-            termtext = "=(" + self.flags[0]
-            for f in self.flags[1:]:
-                termtext = termtext + ',' + f
+            termtext = ""
+            for f in self.flags:
+                if f == "nonipype":
+                    continue 
+                if len(termtext) == 0:
+                    termtext = "=(" + f
+                else:
+                    termtext = termtext + ', ' + f
+
             termtext = termtext + ", %s)"
             print termtext % (self.type)
         elif self.required:
@@ -308,10 +428,17 @@ class CParam:
         e = etree.SubElement(row, "entry", align="center", valign="top")
         e.text = self.type
         e = etree.SubElement(row, "entry", align="center", valign="top")
+
         if len(self.flags) > 0:
-            e.text = "(" + self.flags[0]
-            for f in self.flags[1:]:
-                e.text = e.text + ',' + f
+            first = True
+            for f in self.flags:
+                if f == "nonipype": 
+                    continue
+                if first:
+                    e.text = "(" + f
+                    first = False
+                else:
+                    e.text = e.text + ',' + f
             e.text = e.text + ')'
         elif self.required: 
             e.text = "(required)"
@@ -585,6 +712,7 @@ class CDescription:
     def __init__(self, node):
         self.Example = None 
         self.FreeParams = None
+        self.stdout_is_result = False
         self.option_groups = []
         self.handlers = {}
         for n in node:
@@ -592,6 +720,8 @@ class CDescription:
                 self.name = n.text
             elif n.tag == 'section':
                 self.section = n.text
+            elif n.tag == 'version':
+                self.version = n.text
             elif n.tag == 'whatis':
                 self.whatis = n.text
             elif n.tag == 'description':
@@ -609,6 +739,8 @@ class CDescription:
                 self.author = n.text
             elif n.tag == 'freeparams':
                 self.FreeParams = n.get("name")
+            elif n.tag == "stdout-is-result":
+                self.stdout_is_result = True
             else: 
                 print "unknown tag '%s'"% (n.tag)
         self.anchor = make_sec_ancor("Sec", self.name)
diff --git a/doc/miaxml2html.py b/doc/miaxml2html.py
deleted file mode 100644
index 26b0a03..0000000
--- a/doc/miaxml2html.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/bin/env python 
-
-import sys
-import re
-from lxml import etree
-
-sys.dont_write_bytecode = True
-
-modules = {'miareadxml' : [0, '', 'none://miareadxml.py' ]
-           }
-from miareadxml import parse_file
-
-def make_ancor(text):
-   """remove spaces and hyphens from the input string""" 
-   return re.sub("[ -]", "", text)
-
-class CPatternCollector:
-   def __init__(self, pattern):
-      self.pattern = pattern
-      self.files=[]
-
-      
-def collect_files(arg, dirname, names):
-    for f in names:
-        if fnmatch(f, arg.pattern):
-            arg.files.append(dirname + "/" + f)
-   
-def find_files(root, pattern): 
-   arg = CPatternCollector(pattern)
-   walk(root, collect_files, arg)
-   return arg.files 
-
-def create_text_node(tag, text):
-   node = etree.Element(tag)
-   node.set_text(text)
-
-def get_program(prog):
-   progsec = etree.Element("section", id=make_ancor(prog.name))
-   title = create_text_node("title", prog.name)
-   descr = create_text_node("para", prog.description)
-   basic_usage = create_text_node("code", prog.description)
-   progsec.append(title)
-   progsec.append(descr)
-   return progsec
-   
-
-def get_section(name, programs):
-   section = etree.Element("section", id=make_ancor(name))
-   title = etree.Element("title")
-   title.set_text(name)
-   section.append(title)
-   for p in sec.programs:
-      section.append(get_program(p))
-   return section
-      
-def get_plugin(plugin):
-   section = etree.Element("section", id=make_ancor(name))
-
-def get_plugins(name, plugins):
-   section = etree.Element("section", id=make_ancor(name))
-   title = create_text_node("title", name)
-   section.append(title)
-   for p in plugins:
-      section.append(get_plugin(p))
-   return section 
-                 
-   
-
-files = find_files(".", "mia-*.xml")
-
-descriptions=[]
-
-for f in files:
-   d = parse_file(f)
-   descriptions.append(d)
-
-program_sections = {}
-
-
-plugin_types = {}
-
-for d in descriptions:
-   if not program_sections.has_key(d.section):
-      program_sections[d.section] = []
-   program_sections[d.section].append(d)
-
-   for h in d.handlers:
-      if not plugin_types.has_key(h.name):
-         plugin_types[h.name] = h
-      plugin_types[h.name].append_user(d.name)
-   
-
-
-#Now convert to linuxdoc format - these are also XML files 
-prog_xml = etree.Element("chapter", id="programs")
-title = create_text_node("title", "Program Reference")
-prog_xml.append(title)
-
-for s in program_sections.keys(): 
-   prog_xml.append(get_section(s, program_sections[s]))
-
-
-plug_xml = etree.Element("chapter", id="plugins")
-title = create_text_node("title", "Plugin Reference")
-plug_xml.append(title)
-
-for s in plugin_types.keys(): 
-   plug_xml.append(get_plugins(s, program_sections[s]))
-   
-
-
-
diff --git a/doc/miaxml2man.py b/doc/miaxml2man.py
index 0dbec76..f194a5a 100644
--- a/doc/miaxml2man.py
+++ b/doc/miaxml2man.py
@@ -1,4 +1,4 @@
-#!/bin/env python 
+#!/usr/bin/env python 
 #
 # Copyright (c) Leipzig, Madrid 1999-2012 Gert Wollny
 #
@@ -39,9 +39,6 @@ def get_date_string():
     lt = time.localtime(time.time())
     return "%d %s %d"% (lt.tm_mday, calendar.month_name[lt.tm_mon], lt.tm_year)
 
-def get_version():
-    return "2.0.10"
-
 #taken from http://effbot.org/zone/re-sub.htm#unescape-html
     
 def unescape(text):
@@ -74,7 +71,7 @@ def clean (text):
 
 def write_man_file(descr):
     name = escape_dash(descr.name)
-    print ".TH %s 1 \"%s\" \"%s\"  \"USER COMMANDS\"" %(escape_dash(descr.name), get_date_string(), get_version())
+    print ".TH %s 1 \"%s\" \"v%s\"  \"USER COMMANDS\"" %(escape_dash(descr.name), get_date_string(), descr.version)
     print ".SH NAME"
     print name, 
     print "\- %s" % (clean(descr.whatis))
diff --git a/doc/miaxml2nipype.py b/doc/miaxml2nipype.py
new file mode 100644
index 0000000..35b6ceb
--- /dev/null
+++ b/doc/miaxml2nipype.py
@@ -0,0 +1,366 @@
+#!/usr/bin/env python 
+#
+# Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+
+# this program is used to translate the XML files obtained by running 
+# a mia-* program with --help-xml into a nipype interface 
+
+import sys
+import time
+import calendar
+import string
+import htmlentitydefs
+import re
+from os import path
+
+from argparse import ArgumentParser
+from argparse import RawTextHelpFormatter
+
+sys.dont_write_bytecode = True
+
+modules = {'miareadxml' : [0, '', 'none://miareadxml.py' ]
+           }
+
+
+nipype_header = """from nipype.interfaces.base import (
+        TraitedSpec,
+        CommandLineInputSpec,
+        CommandLine,
+        File,
+        traits
+    )
+import os"""
+
+
+from miareadxml import parse_file
+
+def get_date_string():
+    lt = time.localtime(time.time())
+    return "%d %s %d"% (lt.tm_mday, calendar.month_name[lt.tm_mon], lt.tm_year)
+
+#taken from http://effbot.org/zone/re-sub.htm#unescape-html
+    
+def unescape(text):
+    def fixup(m):
+        text = m.group(0)
+        if text[:2] == "&#":
+            # character reference
+            try:
+                if text[:3] == "&#x":
+                    return unichr(int(text[3:-1], 16))
+                else:
+                    return unichr(int(text[2:-1]))
+            except ValueError:
+                pass
+        else:
+            # named entity
+            try:
+                text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
+            except KeyError:
+                pass
+        return text # leave as is
+    return re.sub("&#?\w+;", fixup, text)
+
+def dash_to_underscore(text): 
+    return re.sub(r'-', r'_', text) 
+
+def clean (text):
+    text = unescape(text)
+    return escape_dash(text) 
+
+
+class  NipypeOutput: 
+    def __init__(self, input_file, output_file):
+        self.input_file = input_file
+        self.output_file = output_file
+        self.descr = parse_file(input_file)
+        self.out=open(output_file, 'w')
+        self.ParamTable = {
+            "2dbounds" : lambda i : self.create_vint_param(i), 
+            "3dbounds" : lambda i : self.create_vint_param(i), 
+            "vshort":    lambda i : self.create_vint_param(i), 
+            "vint":      lambda i : self.create_vint_param(i), 
+            "vlong":     lambda i : self.create_vint_param(i), 
+            "vushort":   lambda i : self.create_vint_param(i), 
+            "vuint":     lambda i : self.create_vint_param(i), 
+            "vulong":    lambda i : self.create_vint_param(i), 
+
+            "2dfvector" :lambda i : self.create_vfloat_param(i), 
+            "3dfvector" :lambda i : self.create_vfloat_param(i), 
+            "vdouble"   :lambda i : self.create_vfloat_param(i), 
+            "vfloat"    :lambda i : self.create_vfloat_param(i), 
+
+            "bool"  : lambda i : self.create_Bool_param(i), 
+            "short" : lambda i : self.create_Integral_param(i), 
+            "int"   : lambda i : self.create_Integral_param(i), 
+            "long"  : lambda i : self.create_Integral_param(i),
+            "ushort": lambda i : self.create_Integral_param(i), 
+            "uint"  : lambda i : self.create_Integral_param(i), 
+            "ulong" : lambda i : self.create_Integral_param(i), 
+            "float" : lambda i : self.create_Float_param(i), 
+            "double": lambda i : self.create_Float_param(i), 
+
+            "vstring": lambda i : self.create_input_VString_param(i), 
+
+            "dict"  : lambda i : self.create_Dict_param(i), 
+            "set"  : lambda i : self.create_Set_param(i), 
+            "factory" : lambda i : self.create_Factory_param(i)
+        }
+        
+
+    def create_trait_input_param_start(self, param, trait, enums=""):
+        dash_removed_name = dash_to_underscore(param.long)
+        # this should be implemented for all python keywords 
+        if dash_removed_name == "lambda":
+            dash_removed_name = dash_removed_name + "_"
+        self.out.write ( "\t{} = traits.{}({} desc=\"\"\"{}\"\"\", ".format(dash_removed_name, 
+                                                                  trait, enums, param.text)), 
+
+    def create_param_tail(self, param):
+        if param.required: 
+            self.out.write (', mandatory = True '), 
+        self.out.write( ')\n')
+
+    def create_Bool_param(self, param):
+        self.create_trait_input_param_start(param, 'Bool')
+        self.out.write('argstr="--{}" '.format(param.long)), 
+        self.create_param_tail(param)
+
+    def  create_vint_param(self, param):
+        self.create_trait_input_param_start(param, 'ListInt')
+        self.out.write('argstr="--{} %s", sep=","'.format(param.long)), 
+        self.create_param_tail(param)
+        
+    def create_vfloat_param(self, param):
+        self.create_trait_input_param_start(param, 'ListFloat')
+        self.out.write('argstr="--{} %s", sep=","'.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_input_VString_param(self, param):
+        self.create_trait_input_param_start(param, 'ListString')
+        self.out.write('argstr="--{} %s", sep=","'.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_Integral_param(self, param):
+        self.create_trait_input_param_start(param, 'Int')
+        self.out.write('argstr="--{} %d" '.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_Float_param(self, param):
+        self.create_trait_input_param_start(param, 'Float')
+        self.out.write('argstr="--{} %f" '.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_Dict_param(self, param):
+        self.create_trait_input_param_start(param, 'Enum', param.get_names_as_string())
+        self.out.write('argstr="--{} %s" '.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_Set_param(self, param):
+        self.create_trait_input_param_start(param, 'Enum', param.get_names_as_string())
+        self.out.write('argstr="--{} %s" '.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_Factory_param(self, param):
+        self.create_trait_input_param_start(param, 'String')
+        self.out.write('argstr="--{} %s" '.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_input_String_param(self, param):
+        self.create_trait_input_param_start(param, 'String')
+        self.out.write('argstr="--{} %s" '.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_input_File_param(self, param):
+        self.create_trait_input_param_start(param, 'File')
+        self.out.write('argstr="--{} %s", exists=True '.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_output_String_param(self, param):
+        self.out.write ( '\t{} = traits.String(desc="{}", '.format(dash_to_underscore(param.long), param.text)), 
+        self.out.write('argstr="--{} %s" '.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_output_File_param(self, param):
+        self.out.write ( '\t{} = File(desc="{}", '.format(dash_to_underscore(param.long), param.text)), 
+        self.out.write('argstr="--{} %s" '.format(param.long)), 
+        self.create_param_tail(param)
+
+    def create_output_File_param_outspec(self, param):
+        self.out.write ( '\t{} = File(desc="{}"'.format(dash_to_underscore(param.long), param.text)), 
+        if param.required: 
+                self.out.write (', exists = True '), 
+        self.out.write( ')\n')
+
+    def write_unknown_type(self, param):
+        print ("WARNING: Unknown  parameter type '{}' encounterd for option '{}', \n".format(param.long, param.type)), 
+    
+    def write_input_spec(self, name, inputs, params):
+
+        self.out.write ("class {}_InputSpec(CommandLineInputSpec):\n".format(name))
+
+        InputTable = self.ParamTable
+        InputTable["string"] = lambda i :self.create_input_File_param(i)
+        InputTable["io"] = lambda i :self.create_input_File_param(i)
+
+        for i in inputs: 
+            InputTable.get(i.type, self.write_unknown_type)(i)
+
+        ParamTableCopy = self.ParamTable
+        ParamTableCopy["string"] = lambda i :self.create_input_String_param(i)
+
+        for i in params: 
+            ParamTableCopy.get(i.type, self.write_unknown_type)(i)
+
+    def write_input_outputs(self, name, outputs, params):
+
+        InputTable = self.ParamTable
+        InputTable["string"] = lambda i :self.create_output_File_param(i)
+        InputTable["io"] = lambda i :self.create_output_File_param(i)
+
+        for i in outputs: 
+            InputTable.get(i.type, self.write_unknown_type)(i)
+
+    def write_input_free_params_spec(self, freeparams):
+        self.out.write ( '\tfree_params = traits.ListStr(desc="Plug-in specifications of type {}", '.format(freeparams)),
+        self.out.write ( 'argstr="%s")')
+
+    def write_output_spec(self, name, outputs, params):
+
+        self.out.write ("class {}_OutputSpec(TraitedSpec):\n".format(name))
+
+        ParamTableCopy = self.ParamTable
+        ParamTableCopy["string"] = lambda i :self.create_output_File_param_outspec(i)
+        ParamTableCopy["io"] = lambda i :self.create_output_File_param_outspec(i)
+
+        for i in outputs: 
+            ParamTableCopy.get(i.type, self.write_unknown_type)(i)
+
+        if self.descr.stdout_is_result:
+            self.out.write ( '\tstdout = traits.Str(\'result from stdout\')\n')
+            
+        self.out.write ("\n")
+
+    def write_task(self, name, outputs):
+
+        self.out.write('class {}(CommandLine):\n'.format(name))
+        self.out.write('\tinput_spec = {}_InputSpec\n'.format(name))
+        self.out.write('\toutput_spec = {}_OutputSpec\n'.format(name))
+        self.out.write('\t_cmd = "{}"\n\n'.format(self.descr.name))
+
+        self.out.write('\tdef _list_outputs(self):\n')
+        self.out.write('\t\toutputs = self.output_spec().get()\n')
+
+        for i in outputs: 
+            # there is a problem here: for files that are given as pattern this will fail. 
+            if i.type == "io" or i.type == "string":
+                name = dash_to_underscore(i.long)
+                self.out.write('\t\toutputs[\'{}\']=os.path.abspath(self.inputs.{})\n'.format(name,name))
+            else:
+                print('Only io or string supported for output, but got {}'.format(i))
+        
+        self.out.write('\t\treturn outputs\n')
+       
+        if self.descr.stdout_is_result:
+            self.out.write('\tdef aggregate_outputs(self, runtime=None, needed_outputs=None):\n')
+            self.out.write('\t\toutputs = super({}, self).aggregate_outputs(runtime, needed_outputs)\n'.format(name))
+            self.out.write('\t\toutputs.stdout = runtime.stdout\n')
+            self.out.write('\t\treturn outputs\n')
+
+    def write_main(self, name):
+
+        self.out.write( 'if __name__ == "__main__":\n')
+        self.out.write( '\tmia_prog = {}()\n'.format(name))
+        self.out.write( '\tprint( mia_prog.cmdline)\n')
+
+    def write_nipype_file(self):
+
+        name = dash_to_underscore(self.descr.name)
+
+        inputs =[]
+        outputs = []
+        params = [] 
+
+        for g in self.descr.option_groups:
+            for o in g.options:
+                if o.no_nipype:
+                    continue 
+                if o.is_input:
+                    inputs.append(o)
+                elif o.is_output:
+                    outputs.append(o)
+                else:
+                    params.append(o)
+
+        self.out.write("# This file was generated by running 'miaxml2nipype.py {} {}'\n".format(
+                self.input_file, self.output_file))
+        self.out.write("# '{}' can be created by running '{} --help-xml >{}'\n".format(
+                self.output_file, self.descr.name, self.output_file))
+        self.out.write("\n")
+
+        self.out.write(nipype_header)
+        self.out.write("\n#\n# Input specification\n#\n"); 
+        self.write_input_spec(name, inputs, params)
+        self.write_input_outputs(name, outputs, params)
+        if self.descr.FreeParams is not None:
+            self.write_input_free_params_spec(self.descr.FreeParams)
+
+        self.out.write("\n#\n# Output specification\n#\n"); 
+        self.write_output_spec(name, outputs, params)
+
+        self.out.write("\n#\n# Task class specification\n#\n"); 
+        self.write_task(name, outputs)
+
+        self.out.write("\n#\n# Main function used for testing\n#\n"); 
+        self.write_main(name)
+   
+  
+
+def SanitizeName(matchobj):
+    s = matchobj.group(0)
+    if s[0] == '-':
+        s = s[1:]
+    return s.upper() 
+         
+
+#
+# main program 
+#
+
+parser = ArgumentParser(description='Convert MIA style command line tools description into a nipype interface.', 
+                                         formatter_class=RawTextHelpFormatter)
+        
+group = parser.add_argument_group('File I/O')
+group.add_argument("-i", "--input",  action="store", required=True,  help="input XML file containing the description")
+group.add_argument("-o", "--output", action="store", help="output file name, if not given, the name will be deducted from the input file")
+group.add_argument("-p", "--outpath", action="store", help="output path for the nipype interface file")
+
+
+options = parser.parse_args()
+
+if options.output is None:
+    (name , ext) = path.splitext(options.input)
+    options.output = re.sub(r'(^[a-z]|-[a-z]|-[0-9][a-z])', SanitizeName, name) + ".py"
+
+if options.outpath is not None:
+    options.output = path.join(options.outpath, options.output)
+
+
+a = NipypeOutput(options.input, options.output)
+a.write_nipype_file()
+
diff --git a/doc/miaxml2sgml.py b/doc/miaxml2sgml.py
index 96f08d6..7e6ddda 100644
--- a/doc/miaxml2sgml.py
+++ b/doc/miaxml2sgml.py
@@ -1,4 +1,4 @@
-#!/bin/env python 
+#!/usr/bin/env python 
 #
 # Copyright (c) Leipzig, Madrid 1999-2012 Gert Wollny
 #
diff --git a/mia/2d/creator/circle.cc b/mia/2d/creator/circle.cc
index dbd5d5e..6855e97 100644
--- a/mia/2d/creator/circle.cc
+++ b/mia/2d/creator/circle.cc
@@ -29,7 +29,6 @@
 NS_BEGIN(creator_circle_2d);
 using namespace mia;
 using namespace std;
-using namespace boost;
 
 class C2DCircleCreator	: public C2DImageCreator {
 public:
diff --git a/mia/2d/filter.cc b/mia/2d/filter.cc
index 1edadab..6ab7bcb 100644
--- a/mia/2d/filter.cc
+++ b/mia/2d/filter.cc
@@ -30,7 +30,6 @@
 #include <mia/template/combiner.cxx>
 
 NS_MIA_BEGIN
-using namespace boost;
 using std::invalid_argument; 
 
 P2DImage  EXPORT_2D run_filter_chain(P2DImage image, size_t nfilters, const char *filters[])
diff --git a/mia/2d/filter/CMakeLists.txt b/mia/2d/filter/CMakeLists.txt
index 932d36f..b16c6b4 100644
--- a/mia/2d/filter/CMakeLists.txt
+++ b/mia/2d/filter/CMakeLists.txt
@@ -26,10 +26,8 @@ SET (NOTHING
   harmmean
   ianiso
   kuwahara
-  labelmap
   lnfft
   midpoint
-  regiongrow
   rgg
   variation
   wmean
@@ -52,6 +50,7 @@ SET(filters2dNew_base
   kmeans
   label 
   labelmap
+  labelscale
   load
   mask
   mean 
diff --git a/mia/2d/filter/labelscale.cc b/mia/2d/filter/labelscale.cc
new file mode 100644
index 0000000..e171a95
--- /dev/null
+++ b/mia/2d/filter/labelscale.cc
@@ -0,0 +1,166 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <mia/2d/filter/labelscale.hh>
+
+NS_BEGIN( labelscale_2dimage_filter)
+
+using namespace mia; 
+using std::vector; 
+using std::pair; 
+using std::make_pair; 
+using std::invalid_argument; 
+
+C2DLabelscale::C2DLabelscale(const C2DBounds& out_size):
+        m_out_size(out_size)
+{
+}
+
+inline pair<unsigned, unsigned> clamp_coord(unsigned i, unsigned di, unsigned ni) 
+{
+	unsigned first = i * di; 
+	unsigned second = first +  di; 
+	return make_pair(first, second > ni? ni: second); 
+}; 
+
+
+template <typename  T>
+T get_max_represented(const vector<T>& buffer)
+{
+        T max_elm = T(); 
+        if (buffer.empty()) 
+                return max_elm; 
+        unsigned int max_num = 1; 
+        unsigned int cur_num = 1; 
+        
+        max_elm = buffer[0]; 
+	
+        T cur_elm = max_elm; 
+        
+        for (auto ib = buffer.begin() + 1; ib != buffer.end() ; ++ib) {
+                if (cur_elm == *ib) {
+                        ++cur_num; 
+                }else{
+                        if (cur_num > max_num) {
+                                max_num = cur_num; 
+                                max_elm = cur_elm; 
+                        }
+                        cur_num = 1; 
+                        cur_elm = *ib; 
+                }
+        }
+        if (cur_num > max_num) {
+                max_elm = cur_elm; 
+        }
+        return max_elm; 
+}; 
+
+template <typename  T>
+typename C2DLabelscale::result_type C2DLabelscale::operator () (const T2DImage<T>& data) const
+{
+        T2DImage<T> *result = new T2DImage<T>(m_out_size, data); 
+
+        C2DBounds block_size = C2DBounds::_1; 
+        C2DFVector coordinate_scale = C2DFVector::_1; 
+
+        if (m_out_size.x  < data.get_size().x ){
+                block_size.x = (data.get_size().x + m_out_size.x - 1) / m_out_size.x; 
+        }else{
+                coordinate_scale.x = float(data.get_size().x) / float(m_out_size.x); 
+        }
+
+                
+        if (m_out_size.y  < data.get_size().y ) {
+                block_size.y = (data.get_size().y + m_out_size.y - 1) / m_out_size.y;
+        }else{
+                coordinate_scale.y = float(data.get_size().y) / float(m_out_size.y); 
+        }
+        
+        vector<T> buffer; 
+        buffer.reserve(block_size.product());
+        auto ir = result->begin(); 
+
+        for (unsigned y = 0; y < m_out_size.y; ++y) {
+                unsigned iy = static_cast<unsigned>(floor(y * coordinate_scale.y)); 
+                auto rangey = clamp_coord(iy, block_size.y, data.get_size().y); 
+                for (unsigned x = 0; x < m_out_size.x; ++x, ++ir) {
+                        unsigned ix = static_cast<unsigned>(floor(x * coordinate_scale.x)); 
+                        auto rangex = clamp_coord(ix, block_size.x, data.get_size().x);
+                        C2DBounds ibegin(rangex.first, rangey.first); 
+                        C2DBounds iend(rangex.second, rangey.second);
+			
+                        buffer.clear(); 
+                        for_each(data.begin_range(ibegin, iend), data.end_range(ibegin, iend), 
+                                 [&buffer](T pixel) {
+                                         buffer.push_back(pixel); 
+                                 });
+                        
+                        sort(buffer.begin(), buffer.end()); 
+                        *ir = get_max_represented(buffer);
+                }
+        }
+        
+        C2DFVector pixel_size = data.get_pixel_size();
+        C2DFVector factor(float(data.get_size().x / float(m_out_size.x) ),
+			  float(data.get_size().y / float(m_out_size.y) ));
+
+	result->set_pixel_size(pixel_size * factor);
+	
+	return P2DImage(result); 
+
+
+}
+
+P2DImage C2DLabelscale::do_filter(const C2DImage& image) const
+{
+        return mia::filter(*this, image); 
+}
+
+C2DLabelscaleFilterPluginFactory::C2DLabelscaleFilterPluginFactory():
+C2DFilterPlugin("labelscale")
+{
+        add_parameter("out-size", new C2DBoundsParameter(m_out_size, true, "target size given as two coma separated values"));
+}
+
+C2DFilter *C2DLabelscaleFilterPluginFactory::do_create()const
+{
+        if (m_out_size.x < 1 || m_out_size.y < 1) {
+                throw create_exception<invalid_argument>("labelscale: Output sizes must be positive (got", 
+                                                         m_out_size, ")"); 
+        }
+        return new C2DLabelscale(m_out_size); 
+}
+
+const std::string C2DLabelscaleFilterPluginFactory::do_get_descr()const
+{
+        return "A filter that only creates output voxels that are already created in "
+                "the input image. Scaling is done by using a voting algorithms that "
+                "selects the target pixel value based on the highest pixel count of a "
+                "certain label in the corresponding source region. If the region "
+                "comprises two labels with the same count, the one with the lower number "
+                "wins.";
+}
+
+extern "C" EXPORT CPluginBase *get_plugin_interface()
+{
+	return new C2DLabelscaleFilterPluginFactory();
+}
+
+
+NS_END
diff --git a/mia/2d/test_combiner.cc b/mia/2d/filter/labelscale.hh
similarity index 56%
copy from mia/2d/test_combiner.cc
copy to mia/2d/filter/labelscale.hh
index ebf7895..4d9f158 100644
--- a/mia/2d/test_combiner.cc
+++ b/mia/2d/filter/labelscale.hh
@@ -18,26 +18,33 @@
  *
  */
 
-#include <stdexcept>
-#include <climits>
-
-#include <mia/internal/autotest.hh>
-#include <boost/filesystem/path.hpp>
 #include <mia/2d/filter.hh>
 
+NS_BEGIN( labelscale_2dimage_filter)
+
+class C2DLabelscale : public mia::C2DFilter {
+public:
+	C2DLabelscale(const mia::C2DBounds& out_size);
+
+	template <class T>
+	typename C2DLabelscale::result_type operator () (const mia::T2DImage<T>& data) const ;
+private:
+	virtual mia::P2DImage do_filter(const mia::C2DImage& image) const;
+
+	mia::C2DBounds m_out_size;
+
+};
+
+class C2DLabelscaleFilterPluginFactory: public mia::C2DFilterPlugin {
+public:
+	C2DLabelscaleFilterPluginFactory();
+private:
+	virtual mia::C2DFilter *do_create()const;
+	virtual const std::string do_get_descr()const;
+        
+	mia::C2DBounds m_out_size;
+};
 
-NS_MIA_USE
-using namespace boost;
-using namespace std;
-namespace bfs=boost::filesystem; 
 
-BOOST_AUTO_TEST_CASE( test_load_plugins ) 
-{	
-	CPathNameArray plugpath;
-	plugpath.push_back(bfs::path("combiner"));
-	C2DImageCombinerPluginHandler::set_search_path(plugpath);
 
-	const C2DImageCombinerPluginHandler::Instance& handler = C2DImageCombinerPluginHandler::instance(); 
-	BOOST_CHECK_EQUAL(handler.size(), 5u); 
-	BOOST_CHECK_EQUAL(handler.get_plugin_names(), "absdiff add div mul sub ");
-}
+NS_END
diff --git a/mia/2d/filter/test_labelscale.cc b/mia/2d/filter/test_labelscale.cc
new file mode 100644
index 0000000..3538824
--- /dev/null
+++ b/mia/2d/filter/test_labelscale.cc
@@ -0,0 +1,128 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mia/internal/plugintester.hh> 
+#include <mia/2d/filter/labelscale.hh>
+
+using namespace labelscale_2dimage_filter; 
+using namespace mia; 
+
+BOOST_AUTO_TEST_CASE ( test_labelscale_downscale ) 
+{
+	const C2DBounds in_size(10, 12); 
+        
+	const unsigned char in_image[120] = {
+                1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 
+                1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 
+                1, 1, 1, 2, 2, 3, 3, 3, 3, 4,
+                5, 5, 5, 2, 2, 2, 3, 3, 4, 4, 
+                5, 5, 2, 2, 2, 3, 3, 3, 4, 4, 
+                5, 5, 5, 2, 7, 2, 3, 3, 3, 3, 
+                5, 6, 5, 7, 7, 7, 7, 3, 3, 3, 
+                6, 6, 6, 7, 7, 7, 7, 3, 3, 3, 
+                6, 6, 8, 7, 7, 7, 7, 3, 3, 3, 
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3, 
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+
+	}; 
+
+	const C2DBounds out_size(5, 3); 
+	const unsigned char out_image[15] = {
+                1,    2,    2,    3,    3, 
+                5,    2,    7,    3,    3, 
+                8,    8,    7,    7,    3
+	}; 
+
+        auto f = BOOST_TEST_create_from_plugin<C2DLabelscaleFilterPluginFactory>("labelscale:out-size=[5,3]"); 
+ 
+
+        C2DUBImage fimage(in_size, in_image );
+	fimage.set_pixel_size(C2DFVector(2.0, 3.0));
+
+        P2DImage scaled = f->filter(fimage);
+        
+        BOOST_CHECK_EQUAL(scaled->get_size(),C2DBounds(5,3));
+
+	const C2DUBImage& fscaled = dynamic_cast<const C2DUBImage& >(*scaled);
+	BOOST_REQUIRE(scaled->get_size() == C2DBounds(5,3));
+
+	BOOST_CHECK_EQUAL(fscaled.get_pixel_size(), C2DFVector(4.0f, 12.f));
+        
+        for (size_t i = 0; i < 15; ++i) {
+		cvdebug() << i << ":" << fscaled[i] << " - " << out_image[i] << '\n'; 
+		BOOST_CHECK_EQUAL(fscaled[i], out_image[i]); 
+	}
+       
+}
+
+
+
+BOOST_AUTO_TEST_CASE ( test_labelscale_upscale ) 
+{
+	const C2DBounds out_size(10, 12); 
+        
+	const unsigned char out_image[120] = {
+                1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 
+                1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 
+                1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+                1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 
+
+                5, 5, 2, 2, 7, 7, 3, 3, 3, 3, 
+                5, 5, 2, 2, 7, 7, 3, 3, 3, 3, 
+                5, 5, 2, 2, 7, 7, 3, 3, 3, 3, 
+                5, 5, 2, 2, 7, 7, 3, 3, 3, 3, 
+
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3, 
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3, 
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+
+	}; 
+
+	const C2DBounds in_size(5, 3); 
+	const unsigned char in_image[15] = {
+                1,    2,    2,    3,    3, 
+                5,    2,    7,    3,    3, 
+                8,    8,    7,    7,    3
+	}; 
+
+        auto f = BOOST_TEST_create_from_plugin<C2DLabelscaleFilterPluginFactory>("labelscale:out-size=[10,12]"); 
+ 
+
+        C2DUBImage fimage(in_size, in_image );
+	fimage.set_pixel_size(C2DFVector(2.0, 3.0));
+
+        P2DImage scaled = f->filter(fimage);
+        
+        BOOST_CHECK_EQUAL(scaled->get_size(),C2DBounds(10,12));
+
+	const C2DUBImage& fscaled = dynamic_cast<const C2DUBImage& >(*scaled);
+	BOOST_REQUIRE(scaled->get_size() == C2DBounds(10,12));
+
+	BOOST_CHECK_EQUAL(fscaled.get_pixel_size(), C2DFVector(1.0f, 0.75f));
+        
+        for (size_t i = 0; i < 120; ++i) {
+		cvdebug() << i << ":" << int(fscaled[i]) << " - " << int(out_image[i]) << '\n'; 
+		BOOST_CHECK_EQUAL(fscaled[i], out_image[i]); 
+	}
+       
+}
+
diff --git a/mia/2d/filtertest.cc b/mia/2d/filtertest.cc
index 1a03c80..ec7a503 100644
--- a/mia/2d/filtertest.cc
+++ b/mia/2d/filtertest.cc
@@ -32,7 +32,6 @@
 
 NS_MIA_BEGIN
 using namespace std;
-using namespace boost;
 namespace bfs=::boost::filesystem;
 using namespace boost::unit_test;
 
diff --git a/mia/2d/fullcost/CMakeLists.txt b/mia/2d/fullcost/CMakeLists.txt
index bd832f5..5545095 100644
--- a/mia/2d/fullcost/CMakeLists.txt
+++ b/mia/2d/fullcost/CMakeLists.txt
@@ -16,5 +16,5 @@
 # along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 
-SET(fullcost image maskedimage)
+SET(fullcost image maskedimage label)
 PLUGINGROUP_WITH_TEST_AND_PREFIX2("2dimage" "fullcost" "${fullcost}" mia2dtest )
diff --git a/mia/2d/fullcost/label.cc b/mia/2d/fullcost/label.cc
new file mode 100644
index 0000000..c448b14
--- /dev/null
+++ b/mia/2d/fullcost/label.cc
@@ -0,0 +1,340 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <cmath>
+
+#include <mia/2d/fullcost/label.hh>
+#include <mia/2d/filter.hh>
+#include <mia/core/distance.hh>
+#include <mia/2d/distance.hh>
+
+NS_MIA_BEGIN
+using namespace std; 
+
+C2DLabelFullCost::C2DLabelFullCost(const std::string& src, 
+				   const std::string& ref, 
+				   double weight, 
+                                   int maxlabels, int debug):
+	C2DFullCost(weight), 
+	m_src_key(C2DImageIOPluginHandler::instance().load_to_pool(src)), 
+	m_ref_key(C2DImageIOPluginHandler::instance().load_to_pool(ref)),
+        m_ref_label_exists(maxlabels), 
+        m_ref_distances(maxlabels), 
+	m_debug(debug)
+{
+	add(::mia::property_gradient);
+}
+
+bool C2DLabelFullCost::do_get_full_size(C2DBounds& size) const
+{
+	TRACE_FUNCTION; 
+	assert(m_src); 
+	if (size == C2DBounds::_0) {
+		size = m_src->get_size(); 
+		return true; 
+	}else
+		return 	size == m_src->get_size(); 
+}
+
+
+double C2DLabelFullCost::do_value(const C2DTransformation& t) const
+{
+	TRACE_FUNCTION; 
+	assert(m_src_scaled.size()); 
+                
+	P2DImage temp  = t(m_src_scaled);
+        const C2DUBImage& temp_ubyte = static_cast<const C2DUBImage&>(*temp); 
+        
+        double result = 0.0; 
+        for (size_t i = 0; i < temp_ubyte.size(); ++i) {
+		double v = value(i, temp_ubyte[i]);
+                result += v; 
+        }
+        return result; 
+}
+
+double C2DLabelFullCost::do_value() const
+{
+	TRACE_FUNCTION; 
+	assert(m_src_scaled.size()); 
+        
+	// one should apply an identity transform here, to ensure that the test image is 
+	// of the same size like the reference image
+        
+        double result = 0.0; 
+        for (size_t i = 0; i < m_src_scaled.size(); ++i) {
+                result += value(i, m_src_scaled[i]);
+        }
+	return result; 
+}
+
+
+double C2DLabelFullCost::do_evaluate(const C2DTransformation& t, CDoubleVector& gradient) const
+{
+	TRACE_FUNCTION; 
+	assert(m_src_scaled.size()); 
+
+	
+	P2DImage temp  = t(m_src_scaled);
+        const C2DUBImage& temp_ubyte = static_cast<const C2DUBImage&>(*temp);
+
+        C2DFVectorfield force(get_current_size()); 
+
+	C2DBounds pos(0,0); 
+	
+	double result = value_and_gradient(0, temp_ubyte[0], force[0], pos, eb_xlow | eb_ylow);
+	int idx = 1; 
+	
+	for (pos.x = 1; pos.x < temp_ubyte.get_size().x - 1; ++pos.x, ++idx) {
+		result += value_and_gradient(idx, temp_ubyte[idx], force[idx], pos, eb_ylow);
+	}
+	result += value_and_gradient(idx, temp_ubyte[idx], force[idx], pos, eb_xhigh | eb_ylow);
+	++idx; 
+	
+	for (pos.y = 1; pos.y < temp_ubyte.get_size().y-1; ++pos.y) {
+		pos.x = 0; 
+		result += value_and_gradient(idx, temp_ubyte[idx], force[idx], pos, eb_xlow);
+		++idx; 
+			
+		for (pos.x = 1; pos.x < temp_ubyte.get_size().x - 1; ++pos.x, ++idx) {
+			result += value_and_gradient(idx, temp_ubyte[idx], force[idx], pos, eb_none);
+		}
+		result += value_and_gradient(idx, temp_ubyte[idx], force[idx], pos, eb_xhigh);
+		++idx; 
+	}
+	
+	result += value_and_gradient(idx, temp_ubyte[idx], force[idx], pos, eb_xlow | eb_yhigh);
+	++idx; 
+
+	for (pos.x = 1; pos.x < temp_ubyte.get_size().x-1; ++pos.x, ++idx) {
+		result += value_and_gradient(idx, temp_ubyte[idx], force[idx], pos, eb_yhigh);
+	}
+	result += value_and_gradient(idx, temp_ubyte[idx], force[idx], pos, eb_xhigh | eb_yhigh);
+	
+
+	// at this point one could inject a hole-filling algorithm to 
+	// add forces inside of the homogen overlapping label regions 
+        
+	t.translate(force, gradient); 
+
+	cvdebug() << "Image cost =" << result << "\n"; 
+	return result; 
+	
+}
+
+void C2DLabelFullCost::do_set_size()
+{
+	TRACE_FUNCTION; 
+	assert(m_src); 
+	assert(m_ref); 
+
+	if (m_src_scaled.size() || m_src_scaled.get_size() != get_current_size() ||
+	    m_ref_scaled.size() || m_ref_scaled.get_size() != get_current_size() ) {
+		if (get_current_size() == m_src->get_size()) {
+			m_src_scaled = static_cast<const C2DUBImage&>(*m_src); 
+			m_ref_scaled = static_cast<const C2DUBImage&>(*m_ref); 
+		}else{
+			stringstream filter_descr; 
+			filter_descr << "labelscale:out-size=[" << get_current_size()<<"]"; 
+			auto scaler = C2DFilterPluginHandler::instance().produce(filter_descr.str()); 
+			assert(scaler); 
+			cvdebug() << "C2DLabelFullCost:scale images to " << get_current_size() << 
+				" using '" << filter_descr.str() << "'\n"; 
+			m_src_scaled = static_cast<const C2DUBImage&>(*scaler->filter(*m_src)); 
+                        m_ref_scaled = static_cast<const C2DUBImage&>(*scaler->filter(*m_ref)); 
+		}
+		prepare_distance_fields(m_ref_scaled); 
+	}
+
+}
+
+void C2DLabelFullCost::prepare_distance_fields( const C2DUBImage &image )
+{
+        assert(image.get_pixel_type() == it_ubyte); 
+
+	static int step = 0; 
+        
+        for (size_t i = 0; i < m_ref_label_exists.size(); ++i) {
+                bool exist = false; 
+                
+                stringstream filter_descr; 
+                filter_descr << "binarize:min=" << i << ",max=" << i; 
+                auto bin = run_filter(image, filter_descr.str().c_str()); 
+        
+                const C2DBitImage& bool_bin = static_cast<const C2DBitImage&>(*bin); 
+                for (auto i = bool_bin.begin(); i != bool_bin.end() && !exist; ++i) 
+                        exist = *i; 
+                
+                m_ref_label_exists[i] = exist; 
+                if (exist) {
+			C2DFImage prep(bool_bin.get_size()); 
+			distance_transform_prepare(bool_bin.begin(), bool_bin.end(), 
+						   prep.begin());
+			
+                        m_ref_distances[i] = distance_transform(prep); 
+			transform(m_ref_distances[i].begin(), m_ref_distances[i].end(), 
+				  m_ref_distances[i].begin(), [](float& x){ return sqrt(x);}); 
+			
+                }
+        }
+	if (m_debug) {
+		for (size_t i = 0; i < m_ref_label_exists.size(); ++i) {
+			if (m_ref_label_exists[i]) {
+				stringstream ofname; 
+				ofname << "dt" << setw(3) << setfill('0') << step 
+				       << "_" << setw(3) << setfill('0') << i << ".v";
+				save_image(ofname.str(), m_ref_distances[i]); 
+			}
+		}
+	}
+}
+
+double C2DLabelFullCost::value(int idx, int label) const
+{
+        // non existent labels will be ignored, since they never can be 
+        // aligned 
+        return m_ref_label_exists[label] ? m_ref_distances[label][idx] : 0.0;
+}
+
+double C2DLabelFullCost::value_and_gradient(int idx, int label, C2DFVector& gradient, 
+					    const C2DBounds& pos, int boundaries) const
+{
+        double result; 
+        
+        if (m_ref_label_exists[label]) {
+		const auto & dref = m_ref_distances[label]; 
+                result = dref[idx]; 
+		if (result > 0.0) {
+			if (boundaries == eb_none) 
+				gradient = dref.get_gradient(idx); 
+			else { // emulate repeat boundary conditions 
+				switch (boundaries & eb_x) {
+				case eb_xlow: 
+					gradient.x = 0.5 * (dref(pos.x + 1, pos.y) - dref(pos.x, pos.y)); 
+					break; 
+				case eb_xhigh: 
+					gradient.x = 0.5 * (dref(pos.x, pos.y) - dref(pos.x - 1, pos.y)); 
+					break; 
+				default:
+					gradient.x = 0.5 * (dref(pos.x + 1, pos.y) - dref(pos.x - 1, pos.y)); 
+				}
+				
+				switch (boundaries & eb_y) {
+				case eb_ylow: 
+					gradient.y = 0.5 * (dref(pos.x, pos.y + 1) - dref(pos.x, pos.y)); 
+					break; 
+				case eb_yhigh: 
+					gradient.y = 0.5 * (dref(pos.x, pos.y) - dref(pos.x, pos.y - 1)); 
+					break; 
+				default:
+					gradient.y = 0.5 * (dref(pos.x, pos.y + 1) - dref(pos.x, pos.y - 1)); 
+				}
+			}
+		}else{
+			gradient = C2DFVector::_0;
+		}
+	}else {
+                result = 0.0; 
+                gradient = C2DFVector::_0;
+        }
+        return result; 
+}
+
+
+void C2DLabelFullCost::do_reinit()
+{
+	TRACE_FUNCTION; 
+	m_src = get_from_pool(m_src_key);
+	m_ref = get_from_pool(m_ref_key);
+	m_src_scaled = C2DUBImage(); 
+	m_ref_scaled = C2DUBImage(); 
+
+	// is this true? Actually the deformed image is used and it is always interpolated on the full 
+	// space of the reference image 
+	if (m_src->get_size() != m_ref->get_size()) 
+		throw runtime_error("C2DLabelFullCost only works with images of equal size"); 
+	
+	if (m_src->get_pixel_size() != m_ref->get_pixel_size()) {
+		cvwarn() << "C2DLabelFullCost: src and reference image are of differnet pixel dimensions:"
+			<< m_src->get_pixel_size() << " vs " << m_ref->get_pixel_size() 
+			<< " This code doesn't honour this.\n"; 
+	}
+        if (m_src->get_pixel_type() != it_ubyte) 
+                throw create_exception<runtime_error>("C2DLabelFullCost only works with (label) "
+                                                      "images of pixel type ubyte, but src has type ", 
+                                                      CPixelTypeDict.get_name(m_src->get_pixel_type()));
+
+        if (m_ref->get_pixel_type() != it_ubyte) 
+                throw create_exception<runtime_error>("C2DLabelFullCost only works with (label) "
+                                                      "images of pixel type ubyte, but ref has type ", 
+                                                      CPixelTypeDict.get_name(m_src->get_pixel_type()));
+}
+
+P2DImage C2DLabelFullCost::get_from_pool(const C2DImageDataKey& key)
+{
+	C2DImageIOPlugin::PData in_image_list = key.get();
+		
+	if (!in_image_list || in_image_list->empty())
+		throw invalid_argument("C2DLabelFullCost: no image available in data pool");
+
+	return (*in_image_list)[0];
+}
+
+
+C2DLabelFullCostPlugin::C2DLabelFullCostPlugin():
+        C2DFullCostPlugin("labelimage"), 
+	m_src_name("src.@"), 
+	m_ref_name("ref.@"), 
+        m_maxlabel(256), 
+	m_debug(0)
+{
+	add_parameter("src", new CStringParameter(m_src_name, CCmdOptionFlags::input, "Study image", 
+			      &C2DImageIOPluginHandler::instance()));
+	add_parameter("ref", new CStringParameter(m_ref_name, CCmdOptionFlags::input, "Reference image", 
+			      &C2DImageIOPluginHandler::instance()));
+	add_parameter("maxlabel", new CIntParameter(m_maxlabel, 2, 32000, false, 
+						    "maximum number of labels to consider"));
+	add_parameter("debug", new CIntParameter(m_debug, 0, 1, false, 
+						    "write the distance transforms to a 3D image"));
+
+}
+
+C2DFullCost *C2DLabelFullCostPlugin::do_create(float weight) const
+{
+	cvdebug() << "create C2DLabelFullCostPlugin with weight= " << weight 
+		  << " src=" << m_src_name << " ref=" << m_ref_name 
+		  << " naxlabels=" << m_maxlabel << "\n";
+	return 	new C2DLabelFullCost(m_src_name, m_ref_name, 
+				     weight, m_maxlabel, m_debug); 
+}
+
+const std::string C2DLabelFullCostPlugin::do_get_descr() const
+{
+	return "Similarity cost function that maps labels of two images and handles "
+                "label-preserving multi-resolution processing."; 
+
+}
+
+extern "C" EXPORT CPluginBase *get_plugin_interface()
+{
+	return new C2DLabelFullCostPlugin();
+}
+
+NS_MIA_END
diff --git a/mia/2d/fullcost/label.hh b/mia/2d/fullcost/label.hh
new file mode 100644
index 0000000..dab3ca9
--- /dev/null
+++ b/mia/2d/fullcost/label.hh
@@ -0,0 +1,97 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef mia_2d_imagefullcost_hh
+#define mia_2d_imagefullcost_hh
+
+
+#include <mia/2d/fullcost.hh>
+#include <mia/2d/imageio.hh>
+#include <mia/2d/cost.hh>
+
+NS_MIA_BEGIN
+
+class EXPORT C2DLabelFullCost : public C2DFullCost {
+public: 
+	C2DLabelFullCost(const std::string& src, 
+                         const std::string& ref, 
+                         double weight, 
+                         int maxlabels, 	
+			 int debug); 
+private: 
+	double do_evaluate(const C2DTransformation& t, CDoubleVector& gradient) const;
+	void do_set_size(); 
+
+	static P2DImage get_from_pool(const C2DImageDataKey& key); 
+
+	double do_value(const C2DTransformation& t) const; 
+	bool do_get_full_size(C2DBounds& size) const; 
+
+        double value(int idx, int label) const; 
+        double value_and_gradient(int idx, int label, C2DFVector& gradient, const C2DBounds& pos, int boundaries) const; 
+        void prepare_distance_fields(const C2DUBImage& image); 
+        
+	double do_value() const; 
+	void do_reinit(); 
+
+	C2DImageDataKey m_src_key;
+	C2DImageDataKey m_ref_key;
+	
+	P2DImage m_src; 
+	P2DImage m_ref; 
+
+	C2DUBImage m_src_scaled; 
+	C2DUBImage m_ref_scaled; 
+
+        std::vector<bool> m_ref_label_exists; 
+        std::vector<C2DFImage> m_ref_distances;
+
+	enum EBoundaries {
+		eb_none = 0, 
+		eb_xlow  = 1, /**< at low x-boundary */ 
+		eb_xhigh = 2, /**< at high x-boundary */  
+		eb_x = 3, /**< at high x-boundary */  
+		eb_ylow = 4,  /**< at low y-boundary */ 
+		eb_yhigh = 8, /**< at high y-boundary */
+		eb_y = 12, /**< any y-boundary */
+	}; 
+ 
+	int m_debug; 
+}; 
+
+// plugin implementation 
+class C2DLabelFullCostPlugin: public C2DFullCostPlugin {
+public: 
+	C2DLabelFullCostPlugin(); 
+private: 
+	C2DFullCost *do_create(float weight) const;
+	const std::string do_get_descr() const;
+
+
+	std::string m_src_name;
+	std::string m_ref_name;
+        int m_maxlabel; 
+	int m_debug; 
+}; 
+
+
+NS_MIA_END
+
+#endif
diff --git a/mia/2d/fullcost/test_label.cc b/mia/2d/fullcost/test_label.cc
new file mode 100644
index 0000000..1cc6738
--- /dev/null
+++ b/mia/2d/fullcost/test_label.cc
@@ -0,0 +1,127 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mia/internal/plugintester.hh> 
+#include <mia/2d/fullcost/label.hh>
+#include <mia/2d/transformfactory.hh>
+
+NS_MIA_USE
+
+
+struct TransformInitFixture {
+	TransformInitFixture(); 
+
+	P2DTransformationFactory tff; 
+}; 
+
+
+BOOST_FIXTURE_TEST_CASE ( test_labeldistance, TransformInitFixture ) 
+{
+        // create two images and do the thing 
+        
+        const unsigned char ref_data[25] = {
+                1, 1, 1, 2, 2, 
+                1, 1, 1, 2, 2, 
+                1, 1, 1, 2, 2, 
+                5, 5, 5, 2, 2, 
+                5, 5, 2, 2, 2, 
+	}; 
+
+        const unsigned char mov_data[25] = {
+                1, 1, 2, 2, 2, 
+                1, 1, 2, 2, 2, 
+                1, 1, 2, 2, 2, 
+                1, 1, 5, 2, 2, 
+                5, 5, 5, 5, 2, 
+	}; 
+
+        const float distances [25] = {
+                0, 0, 1, 0,         0, 
+                0, 0, 1, 0,         0, 
+                0, 0, 1, 0,         0, 
+                1, 1, 0, 0,         0, 
+                0, 0, 1, sqrtf(2.0f), 0,
+        }; 
+        
+	const float gradx [25] = {
+		0, 0, 1, 0, 0, 
+                0, 0, 1, 0, 0, 
+                0, 0, 1, 0, 0, 
+                0, 0, 0, 0, 0, 
+                0, 0, -0.5f * sqrtf(2.0f), -0.5f * (sqrtf(5.0f) - 1.0f), 0 
+	}; 
+
+        const float grady [25] = {
+                0, 0,  0, 0, 0, 
+                0, 0,  0, 0, 0, 
+		0, 0,  0, 0, 0, 
+                -1, -1,  0, 0, 0, 
+		0, 0,-.5f, -.5f * (sqrtf(2.0f) - 1.0f), 0 
+        }; 
+
+        const C2DBounds size(5,5);
+        
+        C2DUBImage *mov_image = new C2DUBImage(size, mov_data );
+        C2DUBImage *ref_image = new C2DUBImage(size, ref_data );
+
+        P2DImage mov(mov_image); 
+        P2DImage ref(ref_image);
+        
+        auto cost = BOOST_TEST_create_from_plugin<C2DLabelFullCostPlugin>("labelimage:maxlabel=7"); 
+        
+        auto t = tff->create(size); 
+	auto params = t->get_parameters(); 
+	std::fill(params.begin(), params.end(), 0.0); 
+	t->set_parameters(params); 
+        
+        save_image("src.@", mov); 
+        save_image("ref.@", ref); 
+
+        cost->reinit();
+        cost->set_size(size); 
+        
+        BOOST_CHECK_CLOSE(cost->cost_value(*t), 6 + sqrt(2.0), 0.01); 
+        BOOST_CHECK_CLOSE(cost->cost_value(), 6 + sqrt(2.0), 0.01); 
+        
+	CDoubleVector gradient(t->degrees_of_freedom()); 
+	double cost_value = cost->evaluate(*t, gradient);
+
+	for(int i = 0; i < 25; ++i) {
+		cvdebug() << "[" << i << "]: (" << gradient[2*i] << ", " << gradient[2*i+1]
+			  << ") expect ("<< gradx[i] << ", " << grady[i] << ")\n"; 
+
+		if (gradx[i] != 0.0) 
+			BOOST_CHECK_CLOSE(gradient[2*i], gradx[i], 0.1); 
+		else 
+			BOOST_CHECK_SMALL(gradient[2*i], 1e-10); 
+		if (grady[i] != 0.0) 
+			BOOST_CHECK_CLOSE(gradient[2*i+1], grady[i], 0.1);
+		else 
+			BOOST_CHECK_SMALL(gradient[2*i+1], 1e-10); 
+	}
+}
+
+
+
+TransformInitFixture::TransformInitFixture():
+        tff(C2DTransformCreatorHandler::instance().produce("vf:imgkernel=[bspline:d=0],imgboundary=zero"))
+{
+        
+}
diff --git a/mia/2d/imageiotest.cc b/mia/2d/imageiotest.cc
index ffb1f4e..9175694 100644
--- a/mia/2d/imageiotest.cc
+++ b/mia/2d/imageiotest.cc
@@ -30,7 +30,6 @@
 
 
 using namespace std;
-using namespace boost;
 using namespace boost::unit_test;
 
 NS_MIA_BEGIN
diff --git a/mia/2d/imagetest.cc b/mia/2d/imagetest.cc
index 884291f..2e33cf1 100644
--- a/mia/2d/imagetest.cc
+++ b/mia/2d/imagetest.cc
@@ -23,7 +23,6 @@
 #include <mia/2d/imagetest.hh>
 
 NS_MIA_BEGIN
-using namespace boost;
 
 template <typename T, typename R>
 struct __compare {
diff --git a/mia/2d/interpolator.cc b/mia/2d/interpolator.cc
index 2a4f681..93387dc 100644
--- a/mia/2d/interpolator.cc
+++ b/mia/2d/interpolator.cc
@@ -34,10 +34,8 @@
 
 NS_MIA_BEGIN
 
-using namespace boost;
 using namespace std; 
 
-
 C2DInterpolatorFactory::C2DInterpolatorFactory(const std::string& kernel, const std::string& bc):
 	m_kernel(produce_spline_kernel(kernel)), 
 	m_xbc(produce_spline_boundary_condition(bc)),
diff --git a/mia/2d/register.cc b/mia/2d/register.cc
index 8b2bf2d..cf4d28b 100644
--- a/mia/2d/register.cc
+++ b/mia/2d/register.cc
@@ -36,7 +36,6 @@
 #include <boost/algorithm/minmax_element.hpp>
 
 NS_MIA_USE
-using namespace boost; 
 using namespace std; 
 
 
@@ -349,7 +348,7 @@ struct FMinMax: public TFilter <pair<float, float> > {
 	template <typename T>
 	pair<float, float> operator ()(const T2DImage<T>& image) const {
 		pair<typename T2DImage<T>::const_iterator, typename T2DImage<T>::const_iterator> 
-			minmax = ::boost::minmax_element(image.begin(), image.end()); 
+			minmax = minmax_element(image.begin(), image.end()); 
 		return pair<float, float>(*minmax.first, *minmax.second); 
 	}
 }; 
diff --git a/mia/2d/test_combiner.cc b/mia/2d/test_combiner.cc
index ebf7895..ee76058 100644
--- a/mia/2d/test_combiner.cc
+++ b/mia/2d/test_combiner.cc
@@ -27,7 +27,6 @@
 
 
 NS_MIA_USE
-using namespace boost;
 using namespace std;
 namespace bfs=boost::filesystem; 
 
diff --git a/mia/2d/test_distance.cc b/mia/2d/test_distance.cc
index 875ece4..0756042 100644
--- a/mia/2d/test_distance.cc
+++ b/mia/2d/test_distance.cc
@@ -26,7 +26,6 @@
 NS_MIA_USE
 
 using namespace std;
-using namespace ::boost;
 
 struct PointLineDistanceFixture {
 
diff --git a/mia/2d/test_filter.cc b/mia/2d/test_filter.cc
index 2c769aa..acae766 100644
--- a/mia/2d/test_filter.cc
+++ b/mia/2d/test_filter.cc
@@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(test_available_filters)
 	set<string> test_data = {
 		"adaptmed", "admean", "aniso", "bandpass", "binarize", "close", "combiner", "convert", "crop", 
 		"dilate", "distance", "downscale", "erode", "gauss", "gradnorm", "invert", "kmeans", 
-		"label", "labelmap", "load", "mask", "mean", "median", "mlv", "ngfnorm", "noise", "open",
+		"label", "labelmap", "labelscale", "load", "mask", "mean", "median", "mlv", "ngfnorm", "noise", "open",
 		"pruning", "regiongrow", "sandp", "scale", "selectbig", "sepconv", "shmean", "sort-label", 
 		"sws", "tee", "thinning", "thresh", "transform", "ws"}; 
 
diff --git a/mia/2d/test_filter_cast.cc b/mia/2d/test_filter_cast.cc
index 6729522..a54e743 100644
--- a/mia/2d/test_filter_cast.cc
+++ b/mia/2d/test_filter_cast.cc
@@ -30,7 +30,6 @@
 
 
 NS_MIA_USE
-using namespace boost;
 using namespace std;
 namespace bmpl=boost::mpl;
 
diff --git a/mia/2d/test_fullcost.cc b/mia/2d/test_fullcost.cc
index a3e0846..b4f77bd 100644
--- a/mia/2d/test_fullcost.cc
+++ b/mia/2d/test_fullcost.cc
@@ -194,8 +194,8 @@ private:
 BOOST_AUTO_TEST_CASE( test_load_plugins ) 
 {	
 	const C2DFullCostPluginHandler::Instance& handler = PrepareFullcostTests::instance().fullcost_handler(); 
-	BOOST_CHECK_EQUAL(handler.size(), 2u); 
-	BOOST_CHECK_EQUAL(handler.get_plugin_names(), "image maskedimage ");
+	BOOST_CHECK_EQUAL(handler.size(), 3u); 
+	BOOST_CHECK_EQUAL(handler.get_plugin_names(), "image labelimage maskedimage ");
 }
 
 #if 0 
diff --git a/mia/2d/test_ica.cc b/mia/2d/test_ica.cc
index a648576..d03dcf8 100644
--- a/mia/2d/test_ica.cc
+++ b/mia/2d/test_ica.cc
@@ -25,7 +25,6 @@
 
 using namespace mia;
 using namespace std;
-using namespace ::boost;
 using namespace boost::unit_test;
 
 const size_t slices = 5;
diff --git a/mia/2d/test_image.cc b/mia/2d/test_image.cc
index 38be58e..13efa1b 100644
--- a/mia/2d/test_image.cc
+++ b/mia/2d/test_image.cc
@@ -32,8 +32,6 @@
 
 
 NS_MIA_USE
-using namespace boost;
-
 
 class CCopyFilter: public TFilter<P2DImage >  {
 public:
diff --git a/mia/2d/test_imageio.cc b/mia/2d/test_imageio.cc
index 44975c5..540daa9 100644
--- a/mia/2d/test_imageio.cc
+++ b/mia/2d/test_imageio.cc
@@ -27,7 +27,6 @@
 
 NS_MIA_USE
 using namespace std; 
-using namespace boost; 
 using namespace boost::unit_test;
 namespace bfs = ::boost::filesystem; 
 
diff --git a/mia/2d/test_interpol.cc b/mia/2d/test_interpol.cc
index 8f6e5d5..8314d30 100644
--- a/mia/2d/test_interpol.cc
+++ b/mia/2d/test_interpol.cc
@@ -36,7 +36,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace boost;
 
 namespace bmpl=boost::mpl;
 
diff --git a/mia/2d/test_modelsolverreg.cc b/mia/2d/test_modelsolverreg.cc
index 0c6f76b..7cf402a 100644
--- a/mia/2d/test_modelsolverreg.cc
+++ b/mia/2d/test_modelsolverreg.cc
@@ -26,7 +26,6 @@
 
 
 NS_MIA_USE
-using namespace boost;
 using namespace std;
 
 
diff --git a/mia/2d/test_nfg.cc b/mia/2d/test_nfg.cc
index 6cd2c5d..c49f139 100644
--- a/mia/2d/test_nfg.cc
+++ b/mia/2d/test_nfg.cc
@@ -27,7 +27,6 @@
 
 
 NS_MIA_USE
-using namespace boost;
 using namespace std;
 
 P2DImage create_test_image()
diff --git a/mia/2d/test_oldnewintegrate.cc b/mia/2d/test_oldnewintegrate.cc
index 6a4d366..1cfe490 100644
--- a/mia/2d/test_oldnewintegrate.cc
+++ b/mia/2d/test_oldnewintegrate.cc
@@ -29,7 +29,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace boost;
 
 namespace bmpl=boost::mpl;
 
diff --git a/mia/2d/test_ppmatrix.cc b/mia/2d/test_ppmatrix.cc
index c7be3d6..8689acf 100644
--- a/mia/2d/test_ppmatrix.cc
+++ b/mia/2d/test_ppmatrix.cc
@@ -18,6 +18,7 @@
  *
  */
 
+#include <cmath>
 #include <mia/internal/autotest.hh>
 
 #include <mia/2d/ppmatrix.hh>
@@ -272,7 +273,7 @@ BOOST_FIXTURE_TEST_CASE( test_divergence_expm2_bspline3_grad, TransformSplineFix
 			ic->x += 0.001; 
 			double test_grad = (graddivp - graddivm)/ 0.002; 
 			cvdebug() << x << " " << y << " (x)\n"; 
-			if (abs(test_grad) > 0.0001)
+			if (fabs(test_grad) > 0.0001)
 				BOOST_CHECK_CLOSE(ig[0], test_grad, 2);
 			
 			ic->y += 0.001; 
@@ -283,7 +284,7 @@ BOOST_FIXTURE_TEST_CASE( test_divergence_expm2_bspline3_grad, TransformSplineFix
 			test_grad = (graddivp - graddivm)/ 0.002; 
 			cvdebug() << x << " " << y << " (y)\n"; 
 			
-			if (abs(test_grad) > 0.0001)
+			if (fabs(test_grad) > 0.0001)
 				BOOST_CHECK_CLOSE(ig[1], test_grad, 2);
 		}
 }
@@ -314,7 +315,7 @@ BOOST_FIXTURE_TEST_CASE( test_rotation_expm2_bspline3_grad, TransformSplineFixtu
 			ic->x += 0.001; 
 			double test_grad = (graddivp - graddivm)/ 0.002; 
 			cvdebug() << x << " " << y << " (x)\n"; 
-			if (abs(test_grad) > 0.0001)
+			if (fabs(test_grad) > 0.0001)
 				BOOST_CHECK_CLOSE(ig[0], test_grad, 2);
 			
 			ic->y += 0.001; 
@@ -325,7 +326,7 @@ BOOST_FIXTURE_TEST_CASE( test_rotation_expm2_bspline3_grad, TransformSplineFixtu
 			test_grad = (graddivp - graddivm)/ 0.002; 
 			cvdebug() << x << " " << y << " (y)\n"; 
 			
-			if (abs(test_grad) > 0.0001)
+			if (fabs(test_grad) > 0.0001)
 				BOOST_CHECK_CLOSE(ig[1], test_grad, 2);
 		}
 }
@@ -356,7 +357,7 @@ BOOST_FIXTURE_TEST_CASE( test_divergence_expm2_bspline3_grad_noiso, TransformSpl
 			ic->x += 0.001; 
 			double test_grad = (graddivp - graddivm)/ 0.002; 
 			cvdebug() << x << " " << y << " (x)\n"; 
-			if (abs(test_grad) > 0.0001)
+			if (fabs(test_grad) > 0.0001)
 				BOOST_CHECK_CLOSE(ig[0], test_grad, 1);
 			
 			ic->y += 0.001; 
@@ -367,7 +368,7 @@ BOOST_FIXTURE_TEST_CASE( test_divergence_expm2_bspline3_grad_noiso, TransformSpl
 			test_grad = (graddivp - graddivm)/ 0.002; 
 			cvdebug() << x << " " << y << " (y)\n"; 
 			
-			if (abs(test_grad) > 0.0001)
+			if (fabs(test_grad) > 0.0001)
 				BOOST_CHECK_CLOSE(ig[1], test_grad, 1);
 		}
 }
@@ -398,7 +399,7 @@ BOOST_FIXTURE_TEST_CASE( test_rotation_expm2_bspline3_grad_noiso, TransformSplin
 			ic->x += 0.001; 
 			double test_grad = (graddivp - graddivm)/ 0.002; 
 			cvdebug() << x << " " << y << " (x)\n"; 
-			if (abs(test_grad) > 0.0001)
+			if (fabs(test_grad) > 0.0001)
 				BOOST_CHECK_CLOSE(ig[0], test_grad, 1);
 			
 			ic->y += 0.001; 
@@ -409,7 +410,7 @@ BOOST_FIXTURE_TEST_CASE( test_rotation_expm2_bspline3_grad_noiso, TransformSplin
 			test_grad = (graddivp - graddivm)/ 0.002; 
 			cvdebug() << x << " " << y << " (y)\n"; 
 			
-			if (abs(test_grad) > 0.0001)
+			if (fabs(test_grad) > 0.0001)
 				BOOST_CHECK_CLOSE(ig[1], test_grad, 1);
 		}
 }
diff --git a/mia/2d/test_regplugins.cc b/mia/2d/test_regplugins.cc
index e73d290..23604aa 100644
--- a/mia/2d/test_regplugins.cc
+++ b/mia/2d/test_regplugins.cc
@@ -30,7 +30,6 @@
 
 NS_MIA_USE
 using namespace std; 
-using namespace boost; 
 using namespace boost::unit_test;
 
 namespace bfs=::boost::filesystem; 
diff --git a/mia/2d/test_segframe.cc b/mia/2d/test_segframe.cc
index cf449ce..d8ee634 100644
--- a/mia/2d/test_segframe.cc
+++ b/mia/2d/test_segframe.cc
@@ -29,7 +29,6 @@
 
 using namespace mia; 
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace xmlpp;
 namespace bfs=boost::filesystem;
diff --git a/mia/2d/test_segmentation.cc b/mia/2d/test_segmentation.cc
index d8a6e46..429712b 100644
--- a/mia/2d/test_segmentation.cc
+++ b/mia/2d/test_segmentation.cc
@@ -33,7 +33,6 @@ namespace bfs=boost::filesystem;
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace xmlpp;
 
diff --git a/mia/2d/test_shape.cc b/mia/2d/test_shape.cc
index 33cb374..08d2867 100644
--- a/mia/2d/test_shape.cc
+++ b/mia/2d/test_shape.cc
@@ -26,7 +26,6 @@
 
 NS_MIA_USE
 using namespace std; 
-using namespace boost;
 
 
 BOOST_AUTO_TEST_CASE( test_2dshape_handler ) 
diff --git a/mia/2d/test_transformfactory.cc b/mia/2d/test_transformfactory.cc
index 63db398..7c3497e 100644
--- a/mia/2d/test_transformfactory.cc
+++ b/mia/2d/test_transformfactory.cc
@@ -26,7 +26,6 @@
 NS_MIA_USE
 
 using namespace std;
-using namespace ::boost;
 using namespace boost::unit_test;
 namespace bfs=boost::filesystem;
 
diff --git a/mia/2d/test_vectorfield_interpolator.cc b/mia/2d/test_vectorfield_interpolator.cc
index ec92320..570be1f 100644
--- a/mia/2d/test_vectorfield_interpolator.cc
+++ b/mia/2d/test_vectorfield_interpolator.cc
@@ -28,7 +28,6 @@
 NS_MIA_USE
 
 using namespace std;
-using namespace ::boost;
 using namespace boost::unit_test;
 namespace bfs=boost::filesystem;
 
diff --git a/mia/2d/test_vfio.cc b/mia/2d/test_vfio.cc
index 5b72380..a94c2bc 100644
--- a/mia/2d/test_vfio.cc
+++ b/mia/2d/test_vfio.cc
@@ -32,7 +32,6 @@
 #include <mia/core/filter.hh>
 
 NS_MIA_USE
-using namespace boost; 
 using namespace std; 
 using namespace boost::unit_test;
 namespace bfs=::boost::filesystem; 
diff --git a/mia/2d/vfiotest.cc b/mia/2d/vfiotest.cc
index 9e25437..77ea934 100644
--- a/mia/2d/vfiotest.cc
+++ b/mia/2d/vfiotest.cc
@@ -33,7 +33,6 @@
 #include <mia/core/filter.hh>
 
 NS_MIA_BEGIN
-using namespace boost;
 using namespace std;
 using namespace boost::unit_test;
 namespace bfs=::boost::filesystem;
diff --git a/mia/3d/datafield.cxx b/mia/3d/datafield.cxx
index 7b6469d..b08714b 100644
--- a/mia/3d/datafield.cxx
+++ b/mia/3d/datafield.cxx
@@ -600,6 +600,42 @@ T3DDatafield<T>::end_range(const C3DBounds& begin, const C3DBounds& end)const
 				    begin_at(end.x, end.y, end.z)); 
 }
 
+template <typename T>
+typename T3DDatafield<T>::range_iterator_with_boundary_flag 
+T3DDatafield<T>::begin_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end)
+{
+	return range_iterator_with_boundary_flag(begin, get_size(), begin, end, 
+						  begin_at(begin.x, begin.y, begin.z)); 
+}
+
+
+
+template <typename T>
+typename T3DDatafield<T>::range_iterator_with_boundary_flag 
+T3DDatafield<T>::end_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end)
+{
+	return range_iterator_with_boundary_flag(end, get_size(), begin, end, 
+							begin_at(end.x, end.y, end.z)); 
+}
+
+
+
+template <typename T>
+typename T3DDatafield<T>::const_range_iterator_with_boundary_flag 
+T3DDatafield<T>::begin_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end)const
+{
+	return const_range_iterator_with_boundary_flag(begin, get_size(), begin, end, 
+							begin_at(begin.x, begin.y, begin.z)); 
+}
+
+template <typename T>
+typename T3DDatafield<T>::const_range_iterator_with_boundary_flag 
+T3DDatafield<T>::end_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end)const
+{
+	return const_range_iterator_with_boundary_flag(end, get_size(), begin, end, 
+							begin_at(end.x, end.y, end.z)); 
+}
+
 
 NS_MIA_END
 
diff --git a/mia/3d/datafield.hh b/mia/3d/datafield.hh
index d8aff60..1f36786 100644
--- a/mia/3d/datafield.hh
+++ b/mia/3d/datafield.hh
@@ -399,6 +399,20 @@ public:
         const_range_iterator end_range(const C3DBounds& begin, const C3DBounds& end)const; 
 
 
+        /** \returns an read/write forward iterator over a subset of the data with indicator for the boundaries. */
+	range_iterator_with_boundary_flag begin_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end); 
+
+        /** \returns the end of a read/write forward iterator over a subset of the data with indicator for the boundaries. */
+	range_iterator_with_boundary_flag end_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end); 
+
+
+        /** \returns an read/write forward iterator over a subset of the data with indicator for the boundaries.  */
+	const_range_iterator_with_boundary_flag begin_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end)const; 
+
+        /** \returns the end of a read/write forward iterator over a subset of the data with indicator for the boundaries. */
+	const_range_iterator_with_boundary_flag end_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end)const; 
+
+
 	/**
 	   Obtain an iterator at position (x,y,z)
 	   The functions ensures, that the field uses a single referenced datafield
diff --git a/mia/3d/fifof/morphological.cc b/mia/3d/fifof/morphological.cc
index beb129c..f5441d6 100644
--- a/mia/3d/fifof/morphological.cc
+++ b/mia/3d/fifof/morphological.cc
@@ -33,7 +33,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace boost;
 
 namespace morphological_fifof {
 
diff --git a/mia/3d/fifof/regiongrow.cc b/mia/3d/fifof/regiongrow.cc
index 6eaef61..6288051 100644
--- a/mia/3d/fifof/regiongrow.cc
+++ b/mia/3d/fifof/regiongrow.cc
@@ -83,7 +83,7 @@ struct FTransform<T, true> {
 template <typename T>
 int C2DRegiongrowFifoFilter::operator ()( const T2DImage<T>& image)
 {
-	const bool is_float = is_floating_point<T>::value;
+	const bool is_float = std::is_floating_point<T>::value;
 	transform(image.begin(), image.end(), m_in_buffer.begin(),
 		  FTransform<T, is_float>(m_probmap[m_class]));
 
diff --git a/mia/3d/filter.cc b/mia/3d/filter.cc
index 1d34f0e..61c9fe2 100644
--- a/mia/3d/filter.cc
+++ b/mia/3d/filter.cc
@@ -28,8 +28,6 @@
 
 NS_MIA_BEGIN
 
-using namespace boost;
-
 template<> const  char * const 
 TPluginHandler<C3DFilterPlugin>::m_help = 
 	"These plug-ins provide 3D image filters. Unless otherwise noted, "
diff --git a/mia/3d/filter/CMakeLists.txt b/mia/3d/filter/CMakeLists.txt
index 277da32..3bbada1 100644
--- a/mia/3d/filter/CMakeLists.txt
+++ b/mia/3d/filter/CMakeLists.txt
@@ -29,6 +29,7 @@ SET(filters3dNew
   invert
   kmeans 
   label
+  labelscale
   load
   lvdownscale
   mask
diff --git a/mia/3d/filter/labelscale.cc b/mia/3d/filter/labelscale.cc
new file mode 100644
index 0000000..60a90b0
--- /dev/null
+++ b/mia/3d/filter/labelscale.cc
@@ -0,0 +1,177 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <mia/3d/filter/labelscale.hh>
+
+NS_BEGIN( labelscale_3dimage_filter)
+
+using namespace mia; 
+using std::vector; 
+using std::pair; 
+using std::make_pair; 
+using std::invalid_argument; 
+
+C3DLabelscale::C3DLabelscale(const C3DBounds& out_size):
+        m_out_size(out_size)
+{
+}
+
+inline pair<unsigned, unsigned> clamp_coord(unsigned i, unsigned di, unsigned ni) 
+{
+	unsigned first = i * di; 
+	unsigned second = first +  di; 
+	return make_pair(first, second > ni? ni: second); 
+}; 
+
+
+template <typename  T>
+T get_max_represented(const vector<T>& buffer)
+{
+        T max_elm = T(); 
+        if (buffer.empty()) 
+                return max_elm; 
+        unsigned int max_num = 1; 
+        unsigned int cur_num = 1; 
+        
+        max_elm = buffer[0]; 
+	
+        T cur_elm = max_elm; 
+        
+        for (auto ib = buffer.begin() + 1; ib != buffer.end() ; ++ib) {
+                if (cur_elm == *ib) {
+                        ++cur_num; 
+                }else{
+                        if (cur_num > max_num) {
+                                max_num = cur_num; 
+                                max_elm = cur_elm; 
+                        }
+                        cur_num = 1; 
+                        cur_elm = *ib; 
+                }
+        }
+        if (cur_num > max_num) {
+                max_elm = cur_elm; 
+        }
+        return max_elm; 
+}; 
+
+template <typename  T>
+typename C3DLabelscale::result_type C3DLabelscale::operator () (const T3DImage<T>& data) const
+{
+        T3DImage<T> *result = new T3DImage<T>(m_out_size, data); 
+
+        C3DBounds block_size = C3DBounds::_1; 
+        C3DFVector coordinate_scale = C3DFVector::_1; 
+
+        if (m_out_size.x  < data.get_size().x ){
+                block_size.x = (data.get_size().x + m_out_size.x - 1) / m_out_size.x; 
+        }else{
+                coordinate_scale.x = float(data.get_size().x) / float(m_out_size.x); 
+        }
+
+        if (m_out_size.y  < data.get_size().y ) {
+                block_size.y = (data.get_size().y + m_out_size.y - 1) / m_out_size.y;
+        }else{
+                coordinate_scale.y = float(data.get_size().y) / float(m_out_size.y); 
+        }
+
+        if (m_out_size.z  < data.get_size().z ) {
+                block_size.z = (data.get_size().z + m_out_size.z - 1) / m_out_size.z;
+        }else{
+                coordinate_scale.z = float(data.get_size().z) / float(m_out_size.z); 
+        }
+        
+        vector<T> buffer; 
+        buffer.reserve(block_size.product());
+        auto ir = result->begin(); 
+
+        for (unsigned z = 0; z < m_out_size.z; ++z) {
+                unsigned iz = static_cast<unsigned>(floor(z * coordinate_scale.z)); 
+                auto rangez = clamp_coord(iz, block_size.z, data.get_size().z); 
+		
+		for (unsigned y = 0; y < m_out_size.y; ++y) {
+			unsigned iy = static_cast<unsigned>(floor(y * coordinate_scale.y)); 
+			auto rangey = clamp_coord(iy, block_size.y, data.get_size().y); 
+			for (unsigned x = 0; x < m_out_size.x; ++x, ++ir) {
+				unsigned ix = static_cast<unsigned>(floor(x * coordinate_scale.x)); 
+				auto rangex = clamp_coord(ix, block_size.x, data.get_size().x);
+				C3DBounds ibegin(rangex.first, rangey.first, rangez.first); 
+				C3DBounds iend(rangex.second, rangey.second, rangez.second);
+				
+				buffer.clear(); 
+				for_each(data.begin_range(ibegin, iend), data.end_range(ibegin, iend), 
+					 [&buffer](T pixel) {
+						 buffer.push_back(pixel); 
+					 });
+				
+				sort(buffer.begin(), buffer.end()); 
+				*ir = get_max_represented(buffer);
+			}
+		}
+	}
+        
+        C3DFVector voxel_size = data.get_voxel_size();
+        C3DFVector factor(float(data.get_size().x / float(m_out_size.x) ),
+			  float(data.get_size().y / float(m_out_size.y) ), 
+			  float(data.get_size().z / float(m_out_size.z) ));
+
+	result->set_voxel_size(voxel_size * factor);
+	
+	return P3DImage(result); 
+
+
+}
+
+P3DImage C3DLabelscale::do_filter(const C3DImage& image) const
+{
+        return mia::filter(*this, image); 
+}
+
+C3DLabelscaleFilterPluginFactory::C3DLabelscaleFilterPluginFactory():
+C3DFilterPlugin("labelscale")
+{
+        add_parameter("out-size", new C3DBoundsParameter(m_out_size, true, "target size given as two coma separated values"));
+}
+
+C3DFilter *C3DLabelscaleFilterPluginFactory::do_create()const
+{
+        if (m_out_size.x < 1 || m_out_size.y < 1 || m_out_size.z < 1) {
+                throw create_exception<invalid_argument>("labelscale: Output sizes must be positive (got", 
+                                                         m_out_size, ")"); 
+        }
+        return new C3DLabelscale(m_out_size); 
+}
+
+const std::string C3DLabelscaleFilterPluginFactory::do_get_descr()const
+{
+        return "A filter that only creates output voxels that are already created in "
+                "the input image. Scaling is done by using a voting algorithms that "
+                "selects the target pixel value based on the highest pixel count of a "
+                "certain label in the corresponding source region. If the region "
+                "comprises two labels with the same count, the one with the lower number "
+                "wins.";
+}
+
+extern "C" EXPORT CPluginBase *get_plugin_interface()
+{
+	return new C3DLabelscaleFilterPluginFactory();
+}
+
+
+NS_END
diff --git a/mia/2d/test_combiner.cc b/mia/3d/filter/labelscale.hh
similarity index 54%
copy from mia/2d/test_combiner.cc
copy to mia/3d/filter/labelscale.hh
index ebf7895..c8d5905 100644
--- a/mia/2d/test_combiner.cc
+++ b/mia/3d/filter/labelscale.hh
@@ -18,26 +18,33 @@
  *
  */
 
-#include <stdexcept>
-#include <climits>
+#include <mia/3d/filter.hh>
 
-#include <mia/internal/autotest.hh>
-#include <boost/filesystem/path.hpp>
-#include <mia/2d/filter.hh>
+NS_BEGIN( labelscale_3dimage_filter)
 
+class C3DLabelscale : public mia::C3DFilter {
+public:
+	C3DLabelscale(const mia::C3DBounds& out_size);
 
-NS_MIA_USE
-using namespace boost;
-using namespace std;
-namespace bfs=boost::filesystem; 
+	template <class T>
+	typename C3DLabelscale::result_type operator () (const mia::T3DImage<T>& data) const ;
+private:
+	virtual mia::P3DImage do_filter(const mia::C3DImage& image) const;
 
-BOOST_AUTO_TEST_CASE( test_load_plugins ) 
-{	
-	CPathNameArray plugpath;
-	plugpath.push_back(bfs::path("combiner"));
-	C2DImageCombinerPluginHandler::set_search_path(plugpath);
+	mia::C3DBounds m_out_size;
 
-	const C2DImageCombinerPluginHandler::Instance& handler = C2DImageCombinerPluginHandler::instance(); 
-	BOOST_CHECK_EQUAL(handler.size(), 5u); 
-	BOOST_CHECK_EQUAL(handler.get_plugin_names(), "absdiff add div mul sub ");
-}
+};
+
+class C3DLabelscaleFilterPluginFactory: public mia::C3DFilterPlugin {
+public:
+	C3DLabelscaleFilterPluginFactory();
+private:
+	virtual mia::C3DFilter *do_create()const;
+	virtual const std::string do_get_descr()const;
+        
+	mia::C3DBounds m_out_size;
+};
+
+
+
+NS_END
diff --git a/mia/3d/filter/test_bandpass.cc b/mia/3d/filter/test_bandpass.cc
index ce1a4ba..2f223c0 100644
--- a/mia/3d/filter/test_bandpass.cc
+++ b/mia/3d/filter/test_bandpass.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 
 BOOST_AUTO_TEST_CASE( test_bandpass )
diff --git a/mia/3d/filter/test_binarize.cc b/mia/3d/filter/test_binarize.cc
index 3f094e7..0a1add4 100644
--- a/mia/3d/filter/test_binarize.cc
+++ b/mia/3d/filter/test_binarize.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 
 
diff --git a/mia/3d/filter/test_convert.cc b/mia/3d/filter/test_convert.cc
index c724579..4a6e64f 100644
--- a/mia/3d/filter/test_convert.cc
+++ b/mia/3d/filter/test_convert.cc
@@ -28,7 +28,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 
 namespace bmpl=boost::mpl;
diff --git a/mia/3d/filter/test_crop.cc b/mia/3d/filter/test_crop.cc
index bd2c226..b881288 100644
--- a/mia/3d/filter/test_crop.cc
+++ b/mia/3d/filter/test_crop.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace crop_3d_filter;
 
diff --git a/mia/3d/filter/test_downscale.cc b/mia/3d/filter/test_downscale.cc
index 06ea0fe..be69298 100644
--- a/mia/3d/filter/test_downscale.cc
+++ b/mia/3d/filter/test_downscale.cc
@@ -24,7 +24,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 namespace bfs=boost::filesystem;
 using namespace downscale_3dimage_filter;
diff --git a/mia/3d/filter/test_gradnorm.cc b/mia/3d/filter/test_gradnorm.cc
index a57c101..f9b4b2d 100644
--- a/mia/3d/filter/test_gradnorm.cc
+++ b/mia/3d/filter/test_gradnorm.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace gradnorm_3dimage_filter;
 
diff --git a/mia/3d/filter/test_growmask.cc b/mia/3d/filter/test_growmask.cc
index d80daec..e6621a8 100644
--- a/mia/3d/filter/test_growmask.cc
+++ b/mia/3d/filter/test_growmask.cc
@@ -25,7 +25,6 @@ namespace bfs=boost::filesystem;
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace growmask_3dimage_filter;
 
diff --git a/mia/3d/filter/test_invert.cc b/mia/3d/filter/test_invert.cc
index 0274550..586ee03 100644
--- a/mia/3d/filter/test_invert.cc
+++ b/mia/3d/filter/test_invert.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 
 BOOST_AUTO_TEST_CASE( test_invert_float )
diff --git a/mia/3d/filter/test_kmeans.cc b/mia/3d/filter/test_kmeans.cc
index 0d30fe2..3052330 100644
--- a/mia/3d/filter/test_kmeans.cc
+++ b/mia/3d/filter/test_kmeans.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace kmeans_3dimage_filter;
 
diff --git a/mia/3d/filter/test_label.cc b/mia/3d/filter/test_label.cc
index fbc92af..a574a83 100644
--- a/mia/3d/filter/test_label.cc
+++ b/mia/3d/filter/test_label.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 namespace bfs=boost::filesystem;
 using namespace label_3dimage_filter;
diff --git a/mia/3d/filter/test_labelscale.cc b/mia/3d/filter/test_labelscale.cc
new file mode 100644
index 0000000..66302a1
--- /dev/null
+++ b/mia/3d/filter/test_labelscale.cc
@@ -0,0 +1,169 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mia/internal/plugintester.hh> 
+#include <mia/3d/filter/labelscale.hh>
+
+using namespace labelscale_3dimage_filter; 
+using namespace mia; 
+
+BOOST_AUTO_TEST_CASE ( test_labelscale_downscale ) 
+{
+	const C3DBounds in_size(10, 4, 6); 
+        
+	const unsigned char in_image[240] = {
+                1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 
+                1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 
+                1, 1, 1, 2, 2, 3, 3, 3, 4, 4,
+                5, 5, 5, 2, 2, 2, 3, 3, 4, 4,
+ 
+                1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 
+                1, 1, 1, 2, 7, 2, 3, 3, 3, 3, 
+                5, 6, 5, 7, 7, 7, 7, 3, 4, 4, 
+                6, 6, 6, 7, 7, 7, 7, 3, 4, 4, 
+
+                1, 1, 1, 7, 7, 7, 7, 3, 3, 3, 
+                1, 1, 1, 8, 7, 7, 7, 7, 3, 3, 
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+
+                1, 1, 1, 7, 6, 6, 6, 3, 3, 3, 
+                1, 1, 1, 8, 6, 6, 6, 7, 3, 3, 
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+
+
+                1, 1, 1, 7, 6, 6, 6, 3, 3, 3, 
+                1, 1, 1, 8, 7, 6, 6, 7, 3, 3, 
+                8, 8, 8, 8, 7, 7, 6, 7, 3, 3,
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+
+                1, 1, 1, 7, 6, 6, 6, 3, 3, 3, 
+                1, 1, 1, 8, 6, 6, 6, 7, 3, 3, 
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+                8, 8, 8, 8, 7, 7, 7, 7, 3, 3,
+
+
+	}; 
+
+	const C3DBounds out_size(5, 2, 3); 
+	const unsigned char out_image[30] = {
+		1, 2, 2, 3, 3, 
+		5, 2, 7, 3, 4, 
+		1, 1, 6, 7, 3, 
+
+		8, 8, 7, 7, 3, 
+		1, 1, 6, 6, 3, 
+		8, 8, 7, 7, 3
+		
+	}; 
+
+        auto f = BOOST_TEST_create_from_plugin<C3DLabelscaleFilterPluginFactory>("labelscale:out-size=[5,2,3]"); 
+ 
+
+        C3DUBImage fimage(in_size, in_image );
+	fimage.set_voxel_size(C3DFVector(2.0, 3.0, 4.0));
+
+        P3DImage scaled = f->filter(fimage);
+        
+        BOOST_CHECK_EQUAL(scaled->get_size(), out_size);
+
+	const C3DUBImage& fscaled = dynamic_cast<const C3DUBImage& >(*scaled);
+	BOOST_REQUIRE(scaled->get_size() == out_size);
+
+	BOOST_CHECK_EQUAL(fscaled.get_voxel_size(), C3DFVector(4.0f, 6.f, 8.0));
+        
+        for (size_t i = 0; i < 30; ++i) {
+		cvdebug() << i << ":" << fscaled[i] << " - " << out_image[i] << '\n'; 
+		BOOST_CHECK_EQUAL(fscaled[i], out_image[i]); 
+	}
+       
+}
+
+
+
+BOOST_AUTO_TEST_CASE ( test_labelscale_upscale ) 
+{
+	const C3DBounds out_size(10, 6, 4); 
+        
+	const unsigned char out_image[240] = {
+                1, 1,   2, 2,   2, 2,   3, 3,   3, 3,
+                1, 1,   2, 2,   2, 2,   3, 3,   3, 3,
+                5, 5,   2, 2,   7, 7,   3, 3,   3, 3,
+                5, 5,   2, 2,   7, 7,   3, 3,   3, 3,
+                8, 8,   8, 8,   7, 7,   7, 7,   3, 3,
+                8, 8,   8, 8,   7, 7,   7, 7,   3, 3,
+
+                1, 1,   2, 2,   2, 2,   3, 3,   3, 3,
+                1, 1,   2, 2,   2, 2,   3, 3,   3, 3,
+                5, 5,   2, 2,   7, 7,   3, 3,   3, 3,
+                5, 5,   2, 2,   7, 7,   3, 3,   3, 3,
+                8, 8,   8, 8,   7, 7,   7, 7,   3, 3,
+                8, 8,   8, 8,   7, 7,   7, 7,   3, 3,
+
+                3, 3,   4, 4,   2, 2,   9, 9,   9, 9,
+                3, 3,   4, 4,   2, 2,   9, 9,   9, 9,
+                5, 5,   2, 2,   2, 2,   3, 3,   6, 6, 
+                5, 5,   2, 2,   2, 2,   3, 3,   6, 6, 
+                8, 8,   1, 1,   3, 3,   1, 1,   3, 3, 
+                8, 8,   1, 1,   3, 3,   1, 1,   3, 3, 
+
+                3, 3,   4, 4,   2, 2,   9, 9,   9, 9,
+                3, 3,   4, 4,   2, 2,   9, 9,   9, 9,
+                5, 5,   2, 2,   2, 2,   3, 3,   6, 6, 
+                5, 5,   2, 2,   2, 2,   3, 3,   6, 6, 
+                8, 8,   1, 1,   3, 3,   1, 1,   3, 3, 
+                8, 8,   1, 1,   3, 3,   1, 1,   3, 3, 
+
+	}; 
+
+	const C3DBounds in_size(5, 3, 2); 
+	const unsigned char in_image[30] = {
+                1,    2,    2,    3,    3, 
+                5,    2,    7,    3,    3, 
+                8,    8,    7,    7,    3,
+                3,    4,    2,    9,    9, 
+                5,    2,    2,    3,    6, 
+                8,    1,    3,    1,    3
+
+	}; 
+
+        auto f = BOOST_TEST_create_from_plugin<C3DLabelscaleFilterPluginFactory>("labelscale:out-size=[10,6,4]"); 
+ 
+
+        C3DUBImage fimage(in_size, in_image );
+	fimage.set_voxel_size(C3DFVector(2.0, 3.0, 4.0));
+
+        P3DImage scaled = f->filter(fimage);
+        
+        BOOST_CHECK_EQUAL(scaled->get_size(), out_size);
+
+	const C3DUBImage& fscaled = dynamic_cast<const C3DUBImage& >(*scaled);
+	BOOST_REQUIRE(scaled->get_size() == out_size);
+
+	BOOST_CHECK_EQUAL(fscaled.get_voxel_size(), C3DFVector(1.0f, 1.5f, 2.0));
+        
+        for (size_t i = 0; i < 240; ++i) {
+		cvdebug() << i << ":" << int(fscaled[i]) << " - " << int(out_image[i]) << '\n'; 
+		BOOST_CHECK_EQUAL(fscaled[i], out_image[i]); 
+	}
+       
+}
+
diff --git a/mia/3d/filter/test_load.cc b/mia/3d/filter/test_load.cc
index 4c353a0..cb84a5c 100644
--- a/mia/3d/filter/test_load.cc
+++ b/mia/3d/filter/test_load.cc
@@ -25,7 +25,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace load_3dimage_filter;
 
diff --git a/mia/3d/filter/test_mask.cc b/mia/3d/filter/test_mask.cc
index 8f88413..0cba453 100644
--- a/mia/3d/filter/test_mask.cc
+++ b/mia/3d/filter/test_mask.cc
@@ -24,7 +24,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace mask_3dimage_filter;
 
diff --git a/mia/3d/filter/test_median.cc b/mia/3d/filter/test_median.cc
index 60d551d..f6966f9 100644
--- a/mia/3d/filter/test_median.cc
+++ b/mia/3d/filter/test_median.cc
@@ -24,7 +24,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace median_3dimage_filter;
 
diff --git a/mia/3d/filter/test_mlv.cc b/mia/3d/filter/test_mlv.cc
index 9ac5ec6..fec1b52 100644
--- a/mia/3d/filter/test_mlv.cc
+++ b/mia/3d/filter/test_mlv.cc
@@ -24,7 +24,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace mlv_3dimage_filter;
 
diff --git a/mia/3d/filter/test_morphological.cc b/mia/3d/filter/test_morphological.cc
index c3699f3..0800c25 100644
--- a/mia/3d/filter/test_morphological.cc
+++ b/mia/3d/filter/test_morphological.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 namespace bfs=boost::filesystem;
 using namespace morph_3dimage_filter;
diff --git a/mia/3d/filter/test_reorient.cc b/mia/3d/filter/test_reorient.cc
index 2e8de09..8e1f5a4 100644
--- a/mia/3d/filter/test_reorient.cc
+++ b/mia/3d/filter/test_reorient.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace reorient_3dimage_filter;
 
diff --git a/mia/3d/filter/test_scale.cc b/mia/3d/filter/test_scale.cc
index fe7399a..dd9108a 100644
--- a/mia/3d/filter/test_scale.cc
+++ b/mia/3d/filter/test_scale.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace scale_3dimage_filter;
 
diff --git a/mia/3d/filter/test_selectbig.cc b/mia/3d/filter/test_selectbig.cc
index 4ee03d1..2a2f06f 100644
--- a/mia/3d/filter/test_selectbig.cc
+++ b/mia/3d/filter/test_selectbig.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace selectbig_3dimage_filter;
 
diff --git a/mia/3d/filter/test_sepconv.cc b/mia/3d/filter/test_sepconv.cc
index be15403..1efee04 100644
--- a/mia/3d/filter/test_sepconv.cc
+++ b/mia/3d/filter/test_sepconv.cc
@@ -23,7 +23,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 namespace bfs=boost::filesystem;
 using namespace sepconv_3dimage_filter;
diff --git a/mia/3d/filter/test_tee.cc b/mia/3d/filter/test_tee.cc
index 67a57a2..700922a 100644
--- a/mia/3d/filter/test_tee.cc
+++ b/mia/3d/filter/test_tee.cc
@@ -25,7 +25,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace ::boost;
 using namespace ::boost::unit_test;
 using namespace tee_3dimage_filter;
 
diff --git a/mia/3d/fullcost/CMakeLists.txt b/mia/3d/fullcost/CMakeLists.txt
index f7f2d59..c324b30 100644
--- a/mia/3d/fullcost/CMakeLists.txt
+++ b/mia/3d/fullcost/CMakeLists.txt
@@ -16,7 +16,7 @@
 # along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 
-SET(fullcost image maskedimage taggedssd)
+SET(fullcost image label maskedimage taggedssd)
 PLUGINGROUP_WITH_TEST_AND_PREFIX2("3dimage" "fullcost" "${fullcost}" mia3d TESTLIBS
   mia3dtest
   )
diff --git a/mia/3d/fullcost/label.cc b/mia/3d/fullcost/label.cc
new file mode 100644
index 0000000..cd9f62b
--- /dev/null
+++ b/mia/3d/fullcost/label.cc
@@ -0,0 +1,321 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <cmath>
+
+#include <mia/3d/fullcost/label.hh>
+#include <mia/3d/filter.hh>
+#include <mia/core/distance.hh>
+#include <mia/3d/distance.hh>
+
+NS_MIA_BEGIN
+using namespace std; 
+
+C3DLabelFullCost::C3DLabelFullCost(const std::string& src, 
+				   const std::string& ref, 
+				   double weight, 
+                                   int maxlabels):
+	C3DFullCost(weight), 
+	m_src_key(C3DImageIOPluginHandler::instance().load_to_pool(src)), 
+	m_ref_key(C3DImageIOPluginHandler::instance().load_to_pool(ref)),
+        m_ref_label_exists(maxlabels), 
+        m_ref_distances(maxlabels)
+{
+	add(::mia::property_gradient);
+}
+
+bool C3DLabelFullCost::do_get_full_size(C3DBounds& size) const
+{
+	TRACE_FUNCTION; 
+	assert(m_src); 
+	if (size == C3DBounds::_0) {
+		size = m_src->get_size(); 
+		return true; 
+	}else
+		return 	size == m_src->get_size(); 
+}
+
+
+double C3DLabelFullCost::do_value(const C3DTransformation& t) const
+{
+	TRACE_FUNCTION; 
+	assert(m_src_scaled.size()); 
+                
+	P3DImage temp  = t(m_src_scaled);
+        const C3DUBImage& temp_ubyte = static_cast<const C3DUBImage&>(*temp); 
+        
+        double result = 0.0; 
+        for (size_t i = 0; i < temp_ubyte.size(); ++i) {
+		double v = value(i, temp_ubyte[i]);
+                result += v; 
+        }
+        return result; 
+}
+
+double C3DLabelFullCost::do_value() const
+{
+	TRACE_FUNCTION; 
+	assert(m_src_scaled.size()); 
+        
+	// one should apply an identity transform here, to ensure that the test image is 
+	// of the same size like the reference image
+        
+        double result = 0.0; 
+        for (size_t i = 0; i < m_src_scaled.size(); ++i) {
+                result += value(i, m_src_scaled[i]);
+        }
+	return result; 
+}
+
+
+double C3DLabelFullCost::do_evaluate(const C3DTransformation& t, CDoubleVector& gradient) const
+{
+	TRACE_FUNCTION; 
+	assert(m_src_scaled.size()); 
+
+	assert("add Z loop"); 
+	P3DImage temp  = t(m_src_scaled);
+        const C3DUBImage& temp_ubyte = static_cast<const C3DUBImage&>(*temp);
+
+        C3DFVectorfield force(get_current_size()); 
+
+	int idx = 0; 
+	auto i = temp_ubyte.begin_range_with_boundary_flags(C3DBounds::_0, temp_ubyte.get_size()); 
+	auto e = temp_ubyte.end_range_with_boundary_flags(C3DBounds::_0, temp_ubyte.get_size());
+	auto ig  = force.begin(); 
+	
+
+	double result = 0.0; 
+	while (i != e) {
+		result += value_and_gradient(idx, i, *ig); 
+		++i; 
+		++ig; 
+		++idx; 
+	}
+
+
+	
+	// at this point one could inject a hole-filling algorithm to 
+	// add forces inside of the homogen overlapping label regions 
+        
+	t.translate(force, gradient); 
+
+	cvdebug() << "Image cost =" << result << "\n"; 
+	return result; 
+	
+}
+
+void C3DLabelFullCost::do_set_size()
+{
+	TRACE_FUNCTION; 
+	assert(m_src); 
+	assert(m_ref); 
+
+	if (m_src_scaled.size() || m_src_scaled.get_size() != get_current_size() ||
+	    m_ref_scaled.size() || m_ref_scaled.get_size() != get_current_size() ) {
+		if (get_current_size() == m_src->get_size()) {
+			m_src_scaled = static_cast<const C3DUBImage&>(*m_src); 
+			m_ref_scaled = static_cast<const C3DUBImage&>(*m_ref); 
+		}else{
+			stringstream filter_descr; 
+			filter_descr << "labelscale:s=[" << get_current_size()<<"]"; 
+			auto scaler = C3DFilterPluginHandler::instance().produce(filter_descr.str()); 
+			assert(scaler); 
+			cvdebug() << "C3DLabelFullCost:scale images to " << get_current_size() << 
+				" using '" << filter_descr.str() << "'\n"; 
+			m_src_scaled = static_cast<const C3DUBImage&>(*scaler->filter(*m_src)); 
+                        m_ref_scaled = static_cast<const C3DUBImage&>(*scaler->filter(*m_ref)); 
+		}
+		prepare_distance_fields(m_ref_scaled); 
+	}
+
+}
+
+void C3DLabelFullCost::prepare_distance_fields( const C3DUBImage &image )
+{
+        assert(image.get_pixel_type() == it_ubyte); 
+
+        
+       
+        for (size_t i = 0; i < m_ref_label_exists.size(); ++i) {
+                bool exist = false; 
+                
+                stringstream filter_descr; 
+                filter_descr << "binarize:min=" << i << ",max=" << i; 
+                auto bin = run_filter(image, filter_descr.str().c_str()); 
+        
+                const C3DBitImage& bool_bin = static_cast<const C3DBitImage&>(*bin); 
+                for (auto i = bool_bin.begin(); i != bool_bin.end() && !exist; ++i) 
+                        exist = *i; 
+                
+                m_ref_label_exists[i] = exist; 
+                if (exist) {
+			C3DFImage prep(bool_bin.get_size()); 
+			distance_transform_prepare(bool_bin.begin(), bool_bin.end(), 
+						   prep.begin());
+			
+                        m_ref_distances[i] = distance_transform(prep); 
+			transform(m_ref_distances[i].begin(), m_ref_distances[i].end(), 
+				  m_ref_distances[i].begin(), [](float& x){ return sqrt(x);}); 
+			
+                }
+        }
+}
+
+double C3DLabelFullCost::value(int idx, int label) const
+{
+        // non existent labels will be ignored, since they never can be 
+        // aligned 
+        return m_ref_label_exists[label] ? m_ref_distances[label][idx] : 0.0;
+}
+
+double C3DLabelFullCost::value_and_gradient(int idx, const C3DUBImage::const_range_iterator_with_boundary_flag& i, C3DFVector& gradient) const
+{
+        double result  = 0.0; 
+        
+        if (m_ref_label_exists[*i]) {
+		const auto & dref = m_ref_distances[*i]; 
+                result = dref[idx]; 
+		if (result > 0.0) {
+			auto boundaries = i.get_boundary_flags(); 
+			if (boundaries == eb_none) 
+				gradient = dref.get_gradient(idx); 
+			else { // emulate repeat boundary conditions 
+				const auto&  pos = i.pos(); 
+				switch (boundaries & eb_x) {
+				case eb_xlow: 
+					gradient.x = 0.5 * (dref(pos.x + 1, pos.y, pos.z) - dref(pos.x, pos.y, pos.z)); 
+					break; 
+				case eb_xhigh: 
+					gradient.x = 0.5 * (dref(pos.x, pos.y, pos.z) - dref(pos.x - 1, pos.y, pos.z)); 
+					break; 
+				default:
+					gradient.x = 0.5 * (dref(pos.x + 1, pos.y, pos.z) - dref(pos.x - 1, pos.y, pos.z)); 
+				}
+				
+				switch (boundaries & eb_y) {
+				case eb_ylow: 
+					gradient.y = 0.5 * (dref(pos.x, pos.y + 1, pos.z) - dref(pos.x, pos.y, pos.z)); 
+					break; 
+				case eb_yhigh: 
+					gradient.y = 0.5 * (dref(pos.x, pos.y, pos.z) - dref(pos.x, pos.y - 1, pos.z)); 
+					break; 
+				default:
+					gradient.y = 0.5 * (dref(pos.x, pos.y + 1, pos.z) - dref(pos.x, pos.y - 1, pos.z)); 
+				}
+				
+				switch (boundaries & eb_z) {
+				case eb_zlow: 
+					gradient.z = 0.5 * (dref(pos.x, pos.y, pos.z + 1) - dref(pos.x, pos.y, pos.z)); 
+					break; 
+				case eb_zhigh: 
+					gradient.z = 0.5 * (dref(pos.x, pos.y, pos.z) - dref(pos.x, pos.y, pos.z - 1)); 
+					break; 
+				default:
+					gradient.z = 0.5 * (dref(pos.x, pos.y, pos.z + 1) - dref(pos.x, pos.y, pos.z - 1)); 
+				}
+
+			}
+		}else{
+			gradient = C3DFVector::_0;
+		}
+	}else {
+                gradient = C3DFVector::_0;
+        }
+        return result; 
+}
+
+
+void C3DLabelFullCost::do_reinit()
+{
+	TRACE_FUNCTION; 
+	m_src = get_from_pool(m_src_key);
+	m_ref = get_from_pool(m_ref_key);
+	m_src_scaled = C3DUBImage(); 
+	m_ref_scaled = C3DUBImage(); 
+
+	// is this true? Actually the deformed image is used and it is always interpolated on the full 
+	// space of the reference image 
+	if (m_src->get_size() != m_ref->get_size()) 
+		throw runtime_error("C3DLabelFullCost only works with images of equal size"); 
+	
+	if (m_src->get_voxel_size() != m_ref->get_voxel_size()) {
+		cvwarn() << "C3DLabelFullCost: src and reference image are of differnet voxel dimensions:"
+			<< m_src->get_voxel_size() << " vs " << m_ref->get_voxel_size() 
+			<< " This code doesn't honour this.\n"; 
+	}
+        if (m_src->get_pixel_type() != it_ubyte) 
+                throw create_exception<runtime_error>("C3DLabelFullCost only works with (label) "
+                                                      "images of voxel type ubyte, but src has type ", 
+                                                      CPixelTypeDict.get_name(m_src->get_pixel_type()));
+
+        if (m_ref->get_pixel_type() != it_ubyte) 
+                throw create_exception<runtime_error>("C3DLabelFullCost only works with (label) "
+                                                      "images of voxel type ubyte, but ref has type ", 
+                                                      CPixelTypeDict.get_name(m_src->get_pixel_type()));
+}
+
+P3DImage C3DLabelFullCost::get_from_pool(const C3DImageDataKey& key)
+{
+	C3DImageIOPlugin::PData in_image_list = key.get();
+		
+	if (!in_image_list || in_image_list->empty())
+		throw invalid_argument("C3DLabelFullCost: no image available in data pool");
+
+	return (*in_image_list)[0];
+}
+
+
+C3DLabelFullCostPlugin::C3DLabelFullCostPlugin():
+        C3DFullCostPlugin("labelimage"), 
+	m_src_name("src.@"), 
+	m_ref_name("ref.@"), 
+        m_maxlabel(256)
+{
+	add_parameter("src", new CStringParameter(m_src_name, CCmdOptionFlags::input, "Study image", 
+			      &C3DImageIOPluginHandler::instance()));
+	add_parameter("ref", new CStringParameter(m_ref_name, CCmdOptionFlags::input, "Reference image", 
+			      &C3DImageIOPluginHandler::instance()));
+	add_parameter("maxlabel", new CIntParameter(m_maxlabel, 2, 32000, false, 
+						    "maximum number of labels to consider"));
+}
+
+C3DFullCost *C3DLabelFullCostPlugin::do_create(float weight) const
+{
+	cvdebug() << "create C3DLabelFullCostPlugin with weight= " << weight 
+		  << " src=" << m_src_name << " ref=" << m_ref_name 
+		  << " naxlabels=" << m_maxlabel << "\n";
+	return 	new C3DLabelFullCost(m_src_name, m_ref_name, 
+				     weight, m_maxlabel); 
+}
+
+const std::string C3DLabelFullCostPlugin::do_get_descr() const
+{
+	return "Similarity cost function that maps labels of two images and handles "
+                "label-preserving multi-resolution processing."; 
+
+}
+
+extern "C" EXPORT CPluginBase *get_plugin_interface()
+{
+	return new C3DLabelFullCostPlugin();
+}
+
+NS_MIA_END
diff --git a/mia/3d/fullcost/label.hh b/mia/3d/fullcost/label.hh
new file mode 100644
index 0000000..8a0299d
--- /dev/null
+++ b/mia/3d/fullcost/label.hh
@@ -0,0 +1,100 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef mia_3d_imagefullcost_hh
+#define mia_3d_imagefullcost_hh
+
+
+#include <mia/3d/fullcost.hh>
+#include <mia/3d/imageio.hh>
+#include <mia/3d/cost.hh>
+
+NS_MIA_BEGIN
+
+class EXPORT C3DLabelFullCost : public C3DFullCost {
+public: 
+	C3DLabelFullCost(const std::string& src, 
+                         const std::string& ref, 
+                         double weight, 
+                         int maxlabels); 
+private: 
+	double do_evaluate(const C3DTransformation& t, CDoubleVector& gradient) const;
+	void do_set_size(); 
+
+	static P3DImage get_from_pool(const C3DImageDataKey& key); 
+
+	double do_value(const C3DTransformation& t) const; 
+	bool do_get_full_size(C3DBounds& size) const; 
+
+        double value(int idx, int label) const; 
+        double value_and_gradient(int idx, const C3DUBImage::const_range_iterator_with_boundary_flag& i,
+				  C3DFVector& gradient) const; 
+        void prepare_distance_fields(const C3DUBImage& image); 
+        
+	double do_value() const; 
+	void do_reinit(); 
+
+	C3DImageDataKey m_src_key;
+	C3DImageDataKey m_ref_key;
+	
+	P3DImage m_src; 
+	P3DImage m_ref; 
+
+	C3DUBImage m_src_scaled; 
+	C3DUBImage m_ref_scaled; 
+
+        std::vector<bool> m_ref_label_exists; 
+        std::vector<C3DFImage> m_ref_distances;
+
+	enum EBoundaries {
+		eb_none = 0, 
+		eb_xlow  = 1, /**< at low x-boundary */ 
+		eb_xhigh = 2, /**< at high x-boundary */  
+		eb_x = 3, /**< at high x-boundary */  
+		eb_ylow = 4,  /**< at low y-boundary */ 
+		eb_yhigh = 8, /**< at high y-boundary */
+		eb_y = 12, /**< any y-boundary */
+		eb_zlow = 0x10,  /**< at low y-boundary */ 
+		eb_zhigh = 0x20, /**< at high y-boundary */
+		eb_z = 0x30, /**< any y-boundary */
+
+	}; 
+ 
+
+}; 
+
+// plugin implementation 
+class C3DLabelFullCostPlugin: public C3DFullCostPlugin {
+public: 
+	C3DLabelFullCostPlugin(); 
+private: 
+	C3DFullCost *do_create(float weight) const;
+	const std::string do_get_descr() const;
+
+
+	std::string m_src_name;
+	std::string m_ref_name;
+        int m_maxlabel; 
+}; 
+
+
+NS_MIA_END
+
+#endif
diff --git a/mia/3d/fullcost/test_label.cc b/mia/3d/fullcost/test_label.cc
new file mode 100644
index 0000000..23454c8
--- /dev/null
+++ b/mia/3d/fullcost/test_label.cc
@@ -0,0 +1,203 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mia/internal/plugintester.hh> 
+#include <mia/3d/fullcost/label.hh>
+#include <mia/3d/transformfactory.hh>
+
+NS_MIA_USE
+
+
+struct TransformInitFixture {
+	TransformInitFixture(); 
+
+	P3DTransformationFactory tff; 
+}; 
+
+
+BOOST_FIXTURE_TEST_CASE ( test_labeldistance, TransformInitFixture ) 
+{
+        // create two images and do the thing 
+        
+
+        const unsigned char mov_data[75] = {
+                1, 1, 2, 2, 2, 
+		1, 1, 2, 2, 2, 
+                1, 1, 1, 2, 2, 
+                1, 1, 5, 2, 2, 
+                5, 5, 5, 5, 2, 
+		
+		1, 1, 3, 2, 2, 
+                1, 1, 2, 2, 2, 
+                1, 1, 1, 2, 2, 
+                1, 5, 5, 2, 2, 
+                5, 5, 5, 5, 2, 
+
+		1, 1, 2, 2, 2, 
+                1, 1, 2, 2, 2, 
+                1, 1, 2, 2, 2, 
+                1, 1, 1, 2, 2, 
+                5, 5, 5, 5, 2, 
+
+	}; 
+
+        const unsigned char ref_data[75] = {
+                1, 1, 1, 2, 2,  1, 1, 1, 2, 2,  1, 1, 1, 2, 2,  5, 5, 5, 2, 2,  5, 5, 2, 2, 2, 
+		1, 1, 3, 2, 2,  1, 1, 1, 2, 2,  1, 1, 1, 2, 2,  5, 5, 5, 2, 2,  5, 5, 2, 2, 2, 
+		1, 1, 1, 2, 2,  1, 1, 1, 2, 2,  1, 1, 1, 2, 2,  5, 5, 2, 2, 2,  5, 5, 2, 2, 2, 
+	}; 
+
+#if 0 
+        const float distances [75] = {
+		0, 0, 1, 0, 0, 
+                0, 0, 1, 0, 0, 
+                0, 0, 0, 0, 0, 
+                1, 1, 0, 0, 0, 
+                0, 0, 1, sqrtf(2.0f), 0, 
+		
+		0, 0, 0, 0, 0, 
+                0, 0, 1, 0, 0, 
+                0, 0, 0, 0, 0, 
+                1, 0, 0, 0, 0, 
+                0, 0, 1, sqrtf(2.0f), 0, 
+
+		0, 0, 1, 0, 0, 
+                0, 0, 1, 0, 0, 
+                0, 0, 1, 0, 0, 
+                1, 1, 1, 0, 0, 
+                0, 0, 1, sqrtf(3.0f), 0
+
+        }; 
+
+#endif 
+        const float gradz [75] = {
+                0, 0, 0, 0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0, 0, 
+                0, 0, 0, 0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0.5f * (sqrtf(2.0f) - sqrtf(3.0f)) , 0, 
+                0, 0, 0, 0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0.5f * (sqrtf(2.0f) - sqrtf(3.0f)), 0 
+
+        }; 
+
+        const float grady [75] = {
+                0, 0,  0, 0, 0, 
+                0, 0,  0, 0, 0, 
+		0, 0,  0, 0, 0, 
+                -1, -1,  0, 0, 0, 
+		0, 0,-.5f, -.5f * (sqrtf(2.0f) - 1.0f), 0, 
+
+                0, 0,  0, 0, 0, 
+                0, 0,  0, 0, 0, 
+		0, 0,  0, 0, 0, 
+                -1,0,  0, 0, 0, 
+		0, 0,-.5f, -.5f * (sqrtf(2.0f) - 1.0f), 0, 
+
+                0, 0,  0, 0, 0, 
+                0, 0,  0, 0, 0, 
+		0, 0,  0.5f, 0, 0, 
+                -1, -1, -1, 0, 0, 
+		0, 0, 0, -.5f * (sqrtf(3.0f) - sqrtf(2.0f)), 0 
+
+        }; 
+        
+	const float gradx [75] = {
+		0, 0, 1, 0, 0, 
+                0, 0, 1, 0, 0, 
+                0, 0, 0, 0, 0, 
+                0, 0, 0, 0, 0, 
+                0, 0, -0.5f * sqrtf(2.0f), -0.5f * (sqrtf(5.0f) - 1.0f), 0, 
+
+		0, 0, 0, 0, 0, 
+                0, 0, 1, 0, 0, 
+                0, 0, 0, 0, 0, 
+                0, 0, 0, 0, 0, 
+                0, 0, -0.5f * sqrtf(2.0f), -0.5f * (sqrtf(5.0f) - 1.0f), 0,
+
+		0, 0, 1, 0, 0, 
+                0, 0, 1, 0, 0, 
+                0, 0, 0.5f * sqrtf(2.0f), 0, 0, 
+                0, 0, -.5f * (sqrtf(2.0f) - 1.0f) , 0, 0, 
+                0, 0, -0.5f * sqrtf(3.0f), -0.5f * (sqrtf(6.0f) - 1.0f), 0 
+
+	}; 
+
+
+
+
+        const C3DBounds size(5,5,3);
+        
+        
+        C3DUBImage *mov_image = new C3DUBImage(size, mov_data );
+        C3DUBImage *ref_image = new C3DUBImage(size, ref_data );
+
+        P3DImage mov(mov_image); 
+        P3DImage ref(ref_image);
+        
+        auto cost = BOOST_TEST_create_from_plugin<C3DLabelFullCostPlugin>("labelimage:maxlabel=7"); 
+        
+        auto t = tff->create(size); 
+	auto params = t->get_parameters(); 
+	std::fill(params.begin(), params.end(), 0.0); 
+	t->set_parameters(params); 
+        
+        save_image("src.@", mov); 
+        save_image("ref.@", ref); 
+
+        cost->reinit();
+        cost->set_size(size); 
+        
+        BOOST_CHECK_CLOSE(cost->cost_value(*t), 15 + 2 * sqrt(2.0) + sqrt(3.0), 0.01); 
+        BOOST_CHECK_CLOSE(cost->cost_value(), 15 + 2 * sqrt(2.0) + sqrt(3.0), 0.01); 
+        
+
+	CDoubleVector gradient(t->degrees_of_freedom()); 
+	double cost_value = cost->evaluate(*t, gradient);
+        BOOST_CHECK_CLOSE(cost_value, 15 + 2 * sqrt(2.0) + sqrt(3.0), 0.01); 
+
+	for(int i = 0; i < 75; ++i) {
+		cvdebug() << "[" << i << "]: (" << gradient[3*i] << ", " << gradient[3*i+1] << ", " << gradient[3*i+2]
+			  << ") expect ("<< gradx[i] << ", " << grady[i] << ", " << gradz[i] << ")\n"; 
+
+		if (gradx[i] != 0.0) 
+			BOOST_CHECK_CLOSE(gradient[3*i], gradx[i], 0.1); 
+		else 
+			BOOST_CHECK_SMALL(gradient[3*i], 1e-10); 
+
+		if (grady[i] != 0.0) 
+			BOOST_CHECK_CLOSE(gradient[3*i+1], grady[i], 0.1);
+		else 
+			BOOST_CHECK_SMALL(gradient[3*i+1], 1e-10); 
+
+		if (gradz[i] != 0.0) 
+			BOOST_CHECK_CLOSE(gradient[3*i+2], gradz[i], 0.1);
+		else 
+			BOOST_CHECK_SMALL(gradient[3*i+2], 1e-10); 
+
+
+	}
+
+}
+
+
+
+
+TransformInitFixture::TransformInitFixture():
+        tff(C3DTransformCreatorHandler::instance().produce("vf:imgkernel=[bspline:d=0],imgboundary=zero"))
+{
+        
+}
diff --git a/mia/3d/image.hh b/mia/3d/image.hh
index fb308ac..554fd7d 100644
--- a/mia/3d/image.hh
+++ b/mia/3d/image.hh
@@ -289,6 +289,27 @@ public:
 	}
 
 
+        /** \returns an read/write forward iterator over a subset of the data with indicator for the boundaries.  */
+        range_iterator_with_boundary_flag begin_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end){
+		return m_image.begin_range_with_boundary_flags(begin, end); 
+	}
+
+        /** \returns the end of a read/write forward iterator over a subset of the data with indicator for the boundaries. */
+        range_iterator_with_boundary_flag end_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end){
+		return m_image.end_range_with_boundary_flags(begin, end); 
+	}
+
+
+        /** \returns an read/write forward iterator over a subset of the data with indicator for the boundaries. 
+            The functions ensures, that the field uses a single referenced datafield */
+        const_range_iterator_with_boundary_flag begin_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end)const{
+		return m_image.begin_range_with_boundary_flags(begin, end); 
+	}
+
+        /** \returns the end of a read/write forward iterator over a subset of the data with indicator for the boundaries. */
+        const_range_iterator_with_boundary_flag end_range_with_boundary_flags(const C3DBounds& begin, const C3DBounds& end)const{
+		return m_image.end_range_with_boundary_flags(begin, end); 
+	}
 
 	/// \returns the all over number of pixels/voxels
 	size_t size() const;
diff --git a/mia/3d/imageiotest.cc b/mia/3d/imageiotest.cc
index 74bf83c..52f6852 100644
--- a/mia/3d/imageiotest.cc
+++ b/mia/3d/imageiotest.cc
@@ -34,9 +34,7 @@
 #include <mia/core/filter.hh>
 
 NS_MIA_BEGIN
-using namespace boost;
 using namespace std;
-using namespace boost::unit_test;
 namespace bfs=::boost::filesystem;
 
 #ifdef WIN32
diff --git a/mia/3d/imagetest.cc b/mia/3d/imagetest.cc
index b0a8731..cf5993a 100644
--- a/mia/3d/imagetest.cc
+++ b/mia/3d/imagetest.cc
@@ -23,7 +23,6 @@
 #include <mia/3d/imagetest.hh>
 
 NS_MIA_BEGIN
-using namespace boost;
 
 template <typename T, typename R>
 struct __compare {
diff --git a/mia/3d/interpolator.cc b/mia/3d/interpolator.cc
index 4ccc080..41d62b5 100644
--- a/mia/3d/interpolator.cc
+++ b/mia/3d/interpolator.cc
@@ -38,7 +38,6 @@
 
 NS_MIA_BEGIN
 
-//using namespace boost;
 using namespace std;
 
 CWeightCache::CWeightCache(int kernel_size, 
diff --git a/mia/3d/multireg.cc b/mia/3d/multireg.cc
index c5c6f67..f1f9d6e 100644
--- a/mia/3d/multireg.cc
+++ b/mia/3d/multireg.cc
@@ -36,7 +36,6 @@
 #include <boost/algorithm/minmax_element.hpp>
 
 NS_MIA_BEGIN
-using namespace boost;
 using namespace std;
 
 
diff --git a/mia/3d/test_combiner.cc b/mia/3d/test_combiner.cc
index f08f305..f31b1fb 100644
--- a/mia/3d/test_combiner.cc
+++ b/mia/3d/test_combiner.cc
@@ -27,7 +27,6 @@
 
 NS_MIA_USE
 using namespace std; 
-using namespace boost;
 namespace bfs=::boost::filesystem; 
 
 static void setup_filter_search_path()
diff --git a/mia/3d/test_cost.cc b/mia/3d/test_cost.cc
index c328655..6ff3c01 100644
--- a/mia/3d/test_cost.cc
+++ b/mia/3d/test_cost.cc
@@ -28,11 +28,8 @@
 
 NS_MIA_USE
 using namespace std; 
-using namespace boost;
 namespace bfs=::boost::filesystem; 
 
-using namespace boost::unit_test;
-
 static void prepare_plugin_path()
 {
 	list< bfs::path> searchpath; 
diff --git a/mia/3d/test_deform.cc b/mia/3d/test_deform.cc
index 8cb1979..ee38a61 100644
--- a/mia/3d/test_deform.cc
+++ b/mia/3d/test_deform.cc
@@ -27,8 +27,6 @@
 NS_MIA_USE
 
 using namespace std;
-using namespace ::boost;
-using namespace boost::unit_test;
 
 struct DeformFixture {
 	DeformFixture();
diff --git a/mia/3d/test_ica.cc b/mia/3d/test_ica.cc
index 2665b56..74f46e4 100644
--- a/mia/3d/test_ica.cc
+++ b/mia/3d/test_ica.cc
@@ -24,7 +24,6 @@
 
 using namespace mia;
 using namespace std;
-using namespace ::boost;
 using namespace boost::unit_test;
 
 const size_t slices = 5;
diff --git a/mia/3d/test_image.cc b/mia/3d/test_image.cc
index 08c6300..8b2b209 100644
--- a/mia/3d/test_image.cc
+++ b/mia/3d/test_image.cc
@@ -31,7 +31,6 @@
 
 
 NS_MIA_USE
-using namespace boost;
 using namespace std;
 
 class CCopyFilter: public TFilter<std::shared_ptr<C3DImage>  > {
diff --git a/mia/3d/test_interpol.cc b/mia/3d/test_interpol.cc
index 860031d..ce0836f 100644
--- a/mia/3d/test_interpol.cc
+++ b/mia/3d/test_interpol.cc
@@ -31,7 +31,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace boost;
 namespace bmpl=boost::mpl;
 
 template <typename T, typename  I, bool is_int>
diff --git a/mia/3d/test_nfg.cc b/mia/3d/test_nfg.cc
index 4f14942..be8f446 100644
--- a/mia/3d/test_nfg.cc
+++ b/mia/3d/test_nfg.cc
@@ -25,7 +25,6 @@
 
 
 NS_MIA_USE
-using namespace boost;
 using namespace std;
 
 const float check_noise_level = sqrt((499.0 - 131.0 * 131.0 / 54.0) / 53.0 );
diff --git a/mia/3d/test_orientation.cc b/mia/3d/test_orientation.cc
index 4cfa842..c0330e1 100644
--- a/mia/3d/test_orientation.cc
+++ b/mia/3d/test_orientation.cc
@@ -27,9 +27,6 @@
 
 NS_MIA_USE
 using namespace std;
-using namespace boost;
-
-using namespace boost::unit_test;
 
 static void run_test_read(const string& id, E3DImageOrientation test_orient, 
 			  const string& expect)
diff --git a/mia/3d/test_regplugins.cc b/mia/3d/test_regplugins.cc
index 3de2d65..346981d 100644
--- a/mia/3d/test_regplugins.cc
+++ b/mia/3d/test_regplugins.cc
@@ -35,7 +35,6 @@ namespace bfs=::boost::filesystem;
 
 NS_MIA_USE
 using namespace std; 
-using namespace boost; 
 
 template <typename P>
 void test_plugin(const P& i)
diff --git a/mia/3d/test_shape.cc b/mia/3d/test_shape.cc
index 7e83651..71a9e80 100644
--- a/mia/3d/test_shape.cc
+++ b/mia/3d/test_shape.cc
@@ -26,7 +26,6 @@
 
 NS_MIA_USE
 using namespace std; 
-using namespace boost;
 namespace bfs=::boost::filesystem; 
 
 static void setup_filter_search_path()
diff --git a/mia/3d/test_transformfactory.cc b/mia/3d/test_transformfactory.cc
index 9e57d23..435d775 100644
--- a/mia/3d/test_transformfactory.cc
+++ b/mia/3d/test_transformfactory.cc
@@ -27,8 +27,6 @@ NS_MIA_USE
 
 
 using namespace std;
-using namespace ::boost;
-using namespace boost::unit_test;
 namespace bfs=boost::filesystem;
 
 struct HandlerTestFixture {
diff --git a/mia/3d/test_vfio.cc b/mia/3d/test_vfio.cc
index 09d0cce..7671dbb 100644
--- a/mia/3d/test_vfio.cc
+++ b/mia/3d/test_vfio.cc
@@ -31,9 +31,7 @@
 #include <mia/3d/vfiotest.hh>
 
 NS_MIA_USE
-using namespace boost; 
 using namespace std; 
-using namespace boost::unit_test;
 namespace bfs=::boost::filesystem; 
 
 static void prepare_handler()
diff --git a/mia/3d/transform/rotbend.cc b/mia/3d/transform/rotbend.cc
index 2ee935c..aad4644 100644
--- a/mia/3d/transform/rotbend.cc
+++ b/mia/3d/transform/rotbend.cc
@@ -39,27 +39,29 @@ C3DFVector C3DRotBendTransformation::apply(const C3DFVector& x) const
 
 C3DFVector C3DRotBendTransformation::transform(const C3DFVector& x)const
 {
+	int offset = m_norot ? 0 : 2; 
 	auto y = m_pre_matrix * x; 
 
-	if (y.x > 0) {
-		const float max_distance = get_size().x - m_rotation_center.x; 
-		y.z += y.x * y.x * m_params[2] / (max_distance * max_distance + 1); 
+	if (y.y > 0) {
+		const float max_distance = get_size().y - m_rotation_center.y; 
+		y.z += y.y * y.y * m_params[offset] / (max_distance * max_distance + 1); 
 	} 
-	else if (y.x < 0) {
-		const float max_distance = m_rotation_center.x; 
-		y.z += y.x * y.x * m_params[3] / (max_distance * max_distance + 1); 
+	else if (y.y < 0) {
+		const float max_distance = m_rotation_center.y; 
+		y.z += y.y * y.y * m_params[offset + 1] / (max_distance * max_distance + 1); 
 	}
 
 	return m_post_matrix * y;
 }
 
-C3DRotBendTransformation::C3DRotBendTransformation(const C3DBounds& size, const C3DFVector& orig, 
+C3DRotBendTransformation::C3DRotBendTransformation(const C3DBounds& size, const C3DFVector& orig, bool norot, 
 						   const C3DInterpolatorFactory& ipf):
 	C3DTransformation(ipf), 
-        m_params(4), 
+        m_params(norot ? 2 : 4), 
         m_relative_origin(orig), 
 	m_rotation_center(C3DFVector(size) * m_relative_origin), 
-	m_size(size)
+	m_size(size), 
+	m_norot(norot)
 {
 	m_pre_matrix.identity();
 	m_post_matrix.identity();
@@ -105,9 +107,11 @@ void C3DRotBendTransformation::set_parameters(const CDoubleVector& params)
         m_pre_matrix.identity(); 
 	m_post_matrix.identity(); 
 	m_pre_matrix.translate( -1.0f * m_rotation_center); 
-
-	m_pre_matrix.rotate_x(m_params[0]); 
-	m_pre_matrix.rotate_y(m_params[1]); 
+	
+	if (!m_norot)  {
+		m_pre_matrix.rotate_x(m_params[0]); 
+		m_pre_matrix.rotate_y(m_params[1]); 
+	}
 
         m_post_matrix.translate(m_rotation_center); 
 }
@@ -119,7 +123,7 @@ const C3DBounds& C3DRotBendTransformation::get_size() const
 
 P3DTransformation C3DRotBendTransformation::do_upscale(const C3DBounds& size) const
 {
-	auto result = new C3DRotBendTransformation(size, m_relative_origin, get_interpolator_factory()); 
+	auto result = new C3DRotBendTransformation(size, m_relative_origin, m_norot, get_interpolator_factory()); 
 	result->set_parameters(m_params); 
 	return P3DTransformation(result);
 }
@@ -180,35 +184,6 @@ void C3DRotBendTransformation::translate(const C3DFVectorfield& gradient, CDoubl
 {
 	
 	assert(0 && !"not yet implemented"); 
-	assert(gradient.get_size() == m_size);
-	assert(params.size() == degrees_of_freedom());
-
-	vector<double> r(params.size(), 0.0);
-
-	auto g = gradient.begin();
-	for (size_t z = 0; z < m_size.z; ++z) {
-		double fy =  - m_rotation_center.y; 
-		for (size_t y = 0; y < m_size.y; ++y, fy += 1.0) {
-			double fx =  - m_rotation_center.x;
-			for (size_t x = 0; x < m_size.x; ++x, ++g, fx += 1.0) {
-				r[0] += -fy * g->x + fx * g->y;
-				
-				// scaling 
-				r[1] += 0; 
-				r[2] += 0;
-				
-
-
-				// shear 
-				r[3] += 0; 
-				r[4] += 0; 
-				r[5] += 0; 
-
-				
-			}
-		}
-	}
-	std::copy(r.begin(), r.end(), params.begin());
 }
 
 
@@ -287,32 +262,35 @@ float C3DRotBendTransformation::pertuberate(C3DFVectorfield& /*v*/) const
 	DEBUG_ASSERT_RELEASE_THROW(false, "C3DRotBendTransformation doesn't implement pertuberate."); 
 }
 
-C3DRotBendTransformCreator::C3DRotBendTransformCreator(const C3DFVector& origin, 
+C3DRotBendTransformCreator::C3DRotBendTransformCreator(const C3DFVector& origin, int norot, 
 						       const C3DInterpolatorFactory& ipf):
 C3DTransformCreator(ipf), 
-	m_origin(origin)
+	m_origin(origin), 
+	m_norot(norot)
 {
 }
 
 P3DTransformation C3DRotBendTransformCreator::do_create(const C3DBounds& size, 
 							const C3DInterpolatorFactory& ipf) const
 {
-	return P3DTransformation(new C3DRotBendTransformation(size, m_origin, ipf));
+	return P3DTransformation(new C3DRotBendTransformation(size, m_origin, m_norot, ipf));
 }
 
 
 
 
 C3DRotBendTransformCreatorPlugin::C3DRotBendTransformCreatorPlugin():
-        C3DTransformCreatorPlugin("rotbend")
+C3DTransformCreatorPlugin("rotbend"), 
+	m_norot(0)
 {
 	add_parameter("origin", new C3DFVectorParameter(m_origin, true, "center of the transformation"));
+	add_parameter("norot", new CIntParameter(m_norot, 0, 1, false, "Don't optimize the rotation"));
 }
 
 
 C3DTransformCreator *C3DRotBendTransformCreatorPlugin::do_create(const C3DInterpolatorFactory& ipf) const
 {
-	return new C3DRotBendTransformCreator(m_origin, ipf);
+	return new C3DRotBendTransformCreator(m_origin, m_norot, ipf);
 }
 
 const std::string C3DRotBendTransformCreatorPlugin::do_get_descr() const
diff --git a/mia/3d/transform/rotbend.hh b/mia/3d/transform/rotbend.hh
index 40ec14a..1ac3c72 100644
--- a/mia/3d/transform/rotbend.hh
+++ b/mia/3d/transform/rotbend.hh
@@ -33,7 +33,7 @@ namespace mia_3dtransform_rotbend {
 
 class EXPORT_3D C3DRotBendTransformation : public mia::C3DTransformation {
 public:
-	C3DRotBendTransformation(const mia::C3DBounds& size, const mia::C3DFVector& orig, 
+	C3DRotBendTransformation(const mia::C3DBounds& size, const mia::C3DFVector& orig, bool norot, 
 				 const mia::C3DInterpolatorFactory& ipf); 
 	
 	mia::C3DFVector apply(const mia::C3DFVector& x) const;
@@ -92,17 +92,20 @@ private:
         mia::C3DFVector m_relative_origin;
         mia::C3DFVector m_rotation_center;
 	mia::C3DBounds m_size;
+	bool m_norot; 
 };
 
 
 class C3DRotBendTransformCreator: public mia::C3DTransformCreator {
 public: 
 	C3DRotBendTransformCreator(const mia::C3DFVector& origin, 
+				   int norot, 
 				   const mia::C3DInterpolatorFactory& ipf); 
 private: 
 	virtual mia::P3DTransformation do_create(const mia::C3DBounds& size, 
 						 const mia::C3DInterpolatorFactory& ipf) const;
 	mia::C3DFVector m_origin; 
+	int m_norot; 
 };
 
 class C3DRotBendTransformCreatorPlugin: public mia::C3DTransformCreatorPlugin {
@@ -112,6 +115,7 @@ public:
 	const std::string do_get_descr() const;
 private:
 	mia::C3DFVector m_origin; 
+	int m_norot; 
 };
 
 
diff --git a/mia/3d/transform/test_rotbend.cc b/mia/3d/transform/test_rotbend.cc
index 4ee2b05..45e1c6d 100644
--- a/mia/3d/transform/test_rotbend.cc
+++ b/mia/3d/transform/test_rotbend.cc
@@ -104,20 +104,20 @@ BOOST_FIXTURE_TEST_CASE( test_rotbend3d_rotation_x, Axis1Fixture )
 BOOST_FIXTURE_TEST_CASE( test_rotbend3d_bend_left, Axis1Fixture )
 {
 	check_transformed_is_expected(2, 2.0, m_origin +  C3DFVector(1, 2, -0.2), 
-				      m_origin + C3DFVector(1, 2, -0.2 + 2.0/(13*13+1) ));
+				      m_origin + C3DFVector(1, 2, -0.2 + 8.0/(24*24+1) ));
 }
 
 BOOST_FIXTURE_TEST_CASE( test_rotbend3d__bend_right, Axis1Fixture )
 {
-	check_transformed_is_expected(3, 3.0, m_origin +  C3DFVector(-3, 2, -0.2), 
-				      m_origin + C3DFVector(-3, 2, -0.2 + 27.0 / (12*12+1)));
+	check_transformed_is_expected(3, 4.0, m_origin +  C3DFVector(-3, -2, -0.2), 
+				      m_origin + C3DFVector(-3, -2, -0.2 + 16.0 / (23*23+1) ));
 }
 
 BOOST_FIXTURE_TEST_CASE( test_affine3d_iterator, ipfFixture )
 {
 	C3DBounds size(10,20,15);
 
-	C3DRotBendTransformation t1(size, C3DFVector(5,9.0f,7.5f), ipf);
+	C3DRotBendTransformation t1(size, C3DFVector(5,9.0f, 7.5f), false, ipf);
 	C3DRotBendTransformation::const_iterator ti = t1.begin();
 	
 	for (size_t z = 0; z < size.z; ++z)
@@ -134,7 +134,7 @@ BOOST_FIXTURE_TEST_CASE( test_affine3d_ranged_iterator, ipfFixture)
 	C3DBounds size(10,20,30);
 	C3DBounds delta(1,2,3); 
 
-	C3DRotBendTransformation t1(size, C3DFVector(5,9.0f,15.5f), ipf);
+	C3DRotBendTransformation t1(size, C3DFVector(5,9.0f,15.5f), false, ipf);
 	auto ti = t1.begin_range(delta, size - delta);
 
 	for (size_t z = delta.z; z < size.z - delta.z; ++z)
@@ -149,7 +149,7 @@ BOOST_FIXTURE_TEST_CASE( test_affine3d_ranged_iterator, ipfFixture)
 Axis1Fixture::Axis1Fixture():
 m_origin(12,23,32), 
         m_size(25, 47, 70), 
-        m_transform(m_size, m_origin / C3DFVector(m_size), ipf)
+        m_transform(m_size, m_origin / C3DFVector(m_size), false, ipf)
 {
 
 }
diff --git a/mia/3d/vfiotest.cc b/mia/3d/vfiotest.cc
index ba18e62..9f3c648 100644
--- a/mia/3d/vfiotest.cc
+++ b/mia/3d/vfiotest.cc
@@ -30,9 +30,8 @@
 #include <mia/3d/vfiotest.hh>
 
 NS_MIA_BEGIN
-using namespace boost;
 using namespace std;
-using namespace boost::unit_test;
+using boost::unit_test::test_suite;
 
 
 const 	C3DFVector voxel(1.0, 2.0, 3.0);
diff --git a/mia/core/CMakeLists.txt b/mia/core/CMakeLists.txt
index 3c42ab2..0f947b4 100644
--- a/mia/core/CMakeLists.txt
+++ b/mia/core/CMakeLists.txt
@@ -69,6 +69,7 @@ SET(MIACORE_SRC_BASE
   revision.cc 
   scaler1d.cc
   seriesstats.cc 
+  selftestcmdoption.cc
   shape.cc 
   slopestatistics.cc
   slopeclassifier.cc
@@ -155,6 +156,7 @@ SET(MIACORE_HEADER_BASE
   scaler1d.hh
   shape.hh shape.cxx
   seriesstats.hh
+  selftestcmdoption.hh
   singular_refobj.hh
   slopestatistics.hh
   slopeclassifier.hh
diff --git a/mia/core/attributes.hh b/mia/core/attributes.hh
index 22cb46e..99480d1 100644
--- a/mia/core/attributes.hh
+++ b/mia/core/attributes.hh
@@ -33,6 +33,7 @@
 #include <stdexcept>
 #include <boost/any.hpp>
 #include <boost/ref.hpp>
+#include <boost/lexical_cast.hpp>
 #include <mia/core/attributetype.hh>
 
 NS_MIA_BEGIN
@@ -560,11 +561,12 @@ int TAttribute<T>::type_id() const
    \remark this should replace the parameter translation methods 
 */
 
+
 template <typename T>
 struct dispatch_attr_string {
 	static std::string val2string(const typename ::boost::reference_wrapper<T>::type value) {
 		std::stringstream sval;
-		sval << value;
+		sval << boost::lexical_cast<std::string>(value);
 		return sval.str();
 	}
 	static T string2val(const std::string& str) {
@@ -582,7 +584,7 @@ struct dispatch_attr_string<std::vector<T> > {
 		std::stringstream sval;
 		sval << value.size();
 		for (size_t i = 0; i < value.size(); ++i)
-			sval << " " << value[i];
+			sval << " " << boost::lexical_cast<std::string>(value[i]);
 		return sval.str();
 	}
 	static std::vector<T> string2val(const std::string& str) {
diff --git a/mia/core/cmdbooloption.cc b/mia/core/cmdbooloption.cc
index 3117072..2b511ed 100644
--- a/mia/core/cmdbooloption.cc
+++ b/mia/core/cmdbooloption.cc
@@ -18,17 +18,21 @@
  *
  */
 
+#include <cassert>
 #include <mia/core/typedescr.hh>
 #include <mia/core/cmdbooloption.hh>
 
 NS_MIA_BEGIN
 
 
-CCmdBoolOption::CCmdBoolOption(bool& value, char short_opt, const char *long_opt, const char *long_help):
-	CCmdOption(short_opt, long_opt, long_help, long_opt, false), 
+CCmdBoolOption::CCmdBoolOption(bool& value, char short_opt, const char *long_opt, const char *long_help, 
+			       CCmdOptionFlags flags):
+	CCmdOption(short_opt, long_opt, long_help, long_opt, flags), 
 	m_value(value)
 {
 	m_value = false; 
+
+	assert(!has_flag(CCmdOptionFlags::required) && "A boolean flag option must not have the flag CCmdOptionFlags::required"); 
 }
 
 bool CCmdBoolOption::do_set_value(const char */*str_value*/)
diff --git a/mia/core/cmdbooloption.hh b/mia/core/cmdbooloption.hh
index ebc2d36..dc8f89a 100644
--- a/mia/core/cmdbooloption.hh
+++ b/mia/core/cmdbooloption.hh
@@ -43,8 +43,9 @@ class EXPORT_CORE CCmdBoolOption : public CCmdOption {
 	   \param short_opt the one letter command line option 
 	   \param long_opt the long command line option 
 	   \param long_help the full help bool that describes the option completely 
+	   \param flags specific flags for the option. Note that passing CCmdOptionFlags::required doesn't make sense. 
 	*/
-	CCmdBoolOption(bool& value, char short_opt, const char *long_opt, const char *long_help);
+	CCmdBoolOption(bool& value, char short_opt, const char *long_opt, const char *long_help, CCmdOptionFlags flags);
  private: 
 	bool do_set_value(const char *str_value);
 	void do_write_value(std::ostream& os) const;
diff --git a/mia/core/cmdlineparser.cc b/mia/core/cmdlineparser.cc
index 138bd1f..452084c 100644
--- a/mia/core/cmdlineparser.cc
+++ b/mia/core/cmdlineparser.cc
@@ -89,6 +89,8 @@ struct CCmdOptionListData {
 	bool copyright;
 	vstream::Level verbose;
 	int max_threads;
+	bool m_selftest_run; 
+	bool m_stdout_is_result; 
 
 	CCmdOptionListData(const SProgramDescription& description); 
 
@@ -125,6 +127,44 @@ struct CCmdOptionListData {
 	ostream *m_log; 
 };
 
+
+/**
+   This option is used to run a selftest. 
+
+   A program can only have one selftest option and all other options that are not 
+   in the Help & Info section are ignored when the selftest option is set. 
+   The selftest is done within a class derived from the CSelftestOption::Callback 
+   class that overrides the Callback::do_run() method. 
+*/
+class EXPORT_CORE CSelftestOption: public CCmdOption {
+public: 
+        /**
+           Test callback base class. 
+
+           The tests to be run must be implemented in the "int do_run() const"  method, and 
+           it must return 0 if the test run successfull. 
+         */
+
+
+
+private: 
+        friend class CCmdOptionList; 
+        /**
+           Constructor of the selftest function 
+        */
+        CSelftestOption(bool& run, int& test_result, CSelftestCallback *callback);
+        
+
+        virtual bool do_set_value(const char *str_value);
+	virtual void do_write_value(std::ostream& os) const;
+        virtual size_t do_get_needed_args() const; 
+        
+        std::unique_ptr<CSelftestCallback> m_callback;
+        int& m_test_result;
+        bool& m_run; 
+        
+}; 
+
 void CCmdOptionListData::set_logstream(ostream& os)
 {
 	m_log  = &os; 
@@ -169,6 +209,8 @@ CCmdOptionListData::CCmdOptionListData(const SProgramDescription& description):
 #else 
 	max_threads(tbb::task_scheduler_init::automatic), 
 #endif 
+	m_selftest_run(false), 
+	m_stdout_is_result(false), 
 	m_log(&std::cout)
 {
 
@@ -185,11 +227,11 @@ CCmdOptionListData::CCmdOptionListData(const SProgramDescription& description):
 	add(make_opt(verbose, g_verbose_dict, "verbose",  'V', 
 		     "verbosity of output, print messages of given level and higher priorities."
 		     " Supported priorities starting at lowest level are:"));
-	add(make_opt(copyright,  "copyright", 0, "print copyright information"));
-	add(make_opt(help,  "help", 'h', "print this help"));
-	add(make_opt(help_xml,  "help-xml", 0, "print help formatted as XML"));
-	add(make_opt(usage,  "usage", '?', "print a short help"));
-	add(make_opt(version,  "version", 0, "print the version number and exit"));
+	add(make_opt(copyright,  "copyright", 0, "print copyright information", CCmdOptionFlags::nonipype));
+	add(make_opt(help,  "help", 'h', "print this help", CCmdOptionFlags::nonipype));
+	add(make_opt(help_xml,  "help-xml", 0, "print help formatted as XML", CCmdOptionFlags::nonipype));
+	add(make_opt(usage,  "usage", '?', "print a short help", CCmdOptionFlags::nonipype));
+	add(make_opt(version,  "version", 0, "print the version number and exit", CCmdOptionFlags::nonipype));
 
 	set_current_group("Processing"); 
 	add(make_opt(max_threads, "threads", 0, "Maxiumum number of threads to use for processing," 
@@ -236,6 +278,7 @@ void CCmdOptionListData::add(const string& group, PCmdOption opt)
 	if (options.find(group) == options.end()) 
 		options[group] = vector<PCmdOption>();
 	options[group].push_back(opt); 
+	opt->add_option(short_map, long_map);
 }
 
 CHistoryRecord CCmdOptionListData::get_values() const
@@ -277,7 +320,8 @@ void CCmdOptionListData::print_help_xml(const char *name_help, const CPluginHand
 	Element* nodeRoot = doc->create_root_node("program");
 	Element* program_name = nodeRoot->add_child("name"); 
 	program_name->set_child_text(name_help); 
-
+	Element*  version_string = nodeRoot->add_child("version"); 
+	version_string->set_child_text(get_revision()); 
 	Element* program_group = nodeRoot->add_child("section"); 
 	program_group->set_child_text(m_program_group); 
 	Element* description = nodeRoot->add_child("description"); 
@@ -286,6 +330,7 @@ void CCmdOptionListData::print_help_xml(const char *name_help, const CPluginHand
 	Element*  short_descr = nodeRoot->add_child("whatis"); 
 	short_descr->set_child_text(m_short_descr); 
 
+
 	ostringstream usage_text; 
 	usage_text << " " << name_help << " "; 
 
@@ -319,6 +364,10 @@ void CCmdOptionListData::print_help_xml(const char *name_help, const CPluginHand
 		free_parameters->set_attribute("name", additional_help->get_descriptor()); 
 		free_parameters->set_attribute("type", "factory"); 
 	}
+	
+	if (m_stdout_is_result) {
+		nodeRoot->add_child("stdout-is-result");
+	}
 		
 	usage_text << "[options]"; 
 	if (additional_help) 
@@ -506,7 +555,7 @@ void CCmdOptionListData::print_usage(const char *name) const
 
 void CCmdOptionListData::print_version(const char *name_help) const
 {
-	*m_log << name_help << " revision:" << get_revision() << "\n\n"; 
+	*m_log << name_help << " version: " << get_revision() << "\n\n"; 
 	*m_log << g_basic_copyright1; 
 	*m_log << get_author(); 
 	*m_log << g_basic_copyright2 << "\n"; 
@@ -527,6 +576,11 @@ void CCmdOptionList::add(const std::string& table, PCmdOption opt)
 	m_impl->add(table, opt);
 }
 
+void CCmdOptionList::add_selftest(int& test_result, CSelftestCallback *callback)
+{
+	m_impl->add("Test", PCmdOption(new CSelftestOption(m_impl->m_selftest_run, test_result, callback))); 
+}
+
 void CCmdOptionList::set_group(const std::string& group)
 {
 	m_impl->set_current_group(group); 
@@ -624,6 +678,11 @@ CCmdOptionList::parse(size_t argc, char *args[], const string& additional_type,
 	return do_parse(argc, (const char **)args, true, additional_help);
 }
 
+void CCmdOptionList::set_stdout_is_result()
+{
+	m_impl->m_stdout_is_result = true; 
+}
+
 struct TBBTaskScheduler {
 	static const tbb::task_scheduler_init& initialize(int max_threads);
 }; 
@@ -720,6 +779,8 @@ CCmdOptionList::do_parse(size_t argc, const char *args[], bool has_additional,
 	} else if (m_impl->copyright) {
 		::print_full_copyright(name_help, m_impl->get_author());
 		return hr_copyright;
+	} else if (m_impl->m_selftest_run) {
+		return hr_selftest; 
 	}
 
 	cverb.set_verbosity(m_impl->verbose);
@@ -776,42 +837,6 @@ CHistoryRecord CCmdOptionList::get_values() const
 	return m_impl->get_values();
 }
 
-CHelpOption::CHelpOption(Callback *cb, char short_opt, const char *long_opt, const char *long_help):
-	CCmdOption(short_opt, long_opt, long_help, NULL, CCmdOptionFlags::none), 
-	m_callback(cb)
-{
-}
-
-void CHelpOption::do_get_long_help_xml(std::ostream& os, xmlpp::Element& parent, 
-				       HandlerHelpMap& /*handler_map*/) const
-{
-	do_get_long_help(os);
-	parent.set_attribute("type", "bool");
-}
-
-
-void CHelpOption::print(std::ostream& os) const
-{
-	m_callback->print(os);
-}
-
-bool CHelpOption::do_set_value(const char */*str_value*/)
-{
-	exit(0); 
-}
-size_t CHelpOption::do_get_needed_args() const
-{
-	return 0; 
-}
-
-void CHelpOption::do_get_long_help(std::ostream& /*os*/) const
-{
-}
-
-void CHelpOption::do_write_value(std::ostream& /*os*/) const
-{
-}
-
 CCmdFlagOption::CCmdFlagOption(int& val, const CFlagString& map, char short_opt, 
 			       const char *long_opt, const char *long_help, 
 			       const char *short_help, 
@@ -849,72 +874,57 @@ size_t CCmdFlagOption::do_get_needed_args() const
 	return 1;
 }
 
-PCmdOption EXPORT_CORE make_opt(int& value, const CFlagString& map, const char *long_opt, 
-				char short_opt,const char *long_help, 
-				const char *short_help, CCmdOptionFlags flags)
-{
-	return PCmdOption(new CCmdFlagOption(value, map, short_opt, long_opt,
-                          long_help, short_help, flags ));
-}
 
-
-PCmdOption EXPORT_CORE make_help_opt(const char *long_opt, char short_opt, 
-				     const char *long_help, CHelpOption::Callback *cb)
+CSelftestOption::CSelftestOption(bool& run, int& test_result, CSelftestCallback *callback):
+        CCmdOption(0, "selftest", "run a self test of the program", 0, 
+                   CCmdOptionFlags::nonipype), 
+        m_callback(callback), 
+        m_test_result(test_result), 
+        m_run(run)
 {
-	return PCmdOption(new CHelpOption(cb, short_opt, long_opt, long_help));
+        
 }
 
-PCmdOption EXPORT_CORE make_opt(std::string& value, const char *long_opt, char short_opt, const char *long_help, 
-				CCmdOptionFlags flags, const CPluginHandlerBase *plugin_hint)
-{
-	return PCmdOption(new CCmdStringOption(value, short_opt, long_opt, long_help, 
-					       flags, plugin_hint)); 
-}
 
-PCmdOption EXPORT_CORE make_opt(bool& value, const char *long_opt, char short_opt, const char *help)
+bool CSelftestOption::do_set_value(const char * /* str_value */)
 {
-	return PCmdOption(new CCmdBoolOption(value, short_opt, long_opt, help ));
+        assert(m_callback); 
+        m_test_result = m_callback->run();
+        m_run = true;
+        return true; 
 }
 
-
-//
-// Implementation of the standard option that holds a value
-//
-#if 0
-CBooleanCmdOption::CBooleanCmdOption(T& val, char short_opt, const char *long_opt, const char *long_help):
-        CCmdOption(short_opt, long_opt, long_help, short_help, flags), 
-	m_value(val)
+void CSelftestOption::do_write_value(std::ostream& /* os */) const
 {
-	m_value = false; 
 }
 
-
-bool CBooleanCmdOption::do_set_value(const char *svalue)
+size_t CSelftestOption::do_get_needed_args() const
 {
-	m_value = true;
-	return true; 
+        return 0; 
 }
 
-
-size_t CBooleanCmdOption::do_get_needed_args() const
+PCmdOption EXPORT_CORE make_opt(int& value, const CFlagString& map, const char *long_opt, 
+				char short_opt,const char *long_help, 
+				const char *short_help, CCmdOptionFlags flags)
 {
-        return 0;
+	return PCmdOption(new CCmdFlagOption(value, map, short_opt, long_opt,
+                          long_help, short_help, flags ));
 }
 
 
-void CBooleanCmdOption::do_get_long_help(std::ostream& /*os*/) const
+PCmdOption EXPORT_CORE make_opt(std::string& value, const char *long_opt, char short_opt, const char *long_help, 
+				CCmdOptionFlags flags, const CPluginHandlerBase *plugin_hint)
 {
+	return PCmdOption(new CCmdStringOption(value, short_opt, long_opt, long_help, 
+					       flags, plugin_hint)); 
 }
 
-
-void CBooleanCmdOption::do_write_value(std::ostream& /*os*/) const
+PCmdOption EXPORT_CORE make_opt(bool& value, const char *long_opt, char short_opt, const char *help, 
+				CCmdOptionFlags flags)
 {
+	return PCmdOption(new CCmdBoolOption(value, short_opt, long_opt, help, flags ));
 }
 
-const std::string CBooleanCmdOption::do_get_value_as_string() const
-{
-	return m_value ? "true" : "false";
-}
-#endif 
+
 
 NS_MIA_END
diff --git a/mia/core/cmdlineparser.hh b/mia/core/cmdlineparser.hh
index 773d5ef..acce537 100644
--- a/mia/core/cmdlineparser.hh
+++ b/mia/core/cmdlineparser.hh
@@ -30,12 +30,12 @@
 #include <string>
 #include <iterator>
 #include <mia/core/cmdoption.hh>
-#include <mia/core/cmdoption.hh>
 #include <mia/core/typedescr.hh>
 #include <mia/core/paramoption.hh>
 #include <mia/core/dictmap.hh>
 #include <mia/core/flagstring.hh>
 #include <mia/core/handlerbase.hh>
+#include <mia/core/selftestcmdoption.hh>
 
 NS_MIA_BEGIN
 
@@ -159,68 +159,6 @@ private:
 
 /**
    \ingroup cmdline
-   \brief A command line option that will appear in the help group 
-   and exits the program after printing the help. 
-
-   Option that will appear in the help group and setting it will 
-   always terminate the program after printing out the requested 
-   help. 
- */
-class EXPORT_CORE CHelpOption: public CCmdOption {
-public:
-
-	/**
-	   \ingroup cmdline
-	   \brief Interface for the callback to print the help assositated with the given option.
-	 */
-	class Callback {
-	public:
-		/**
-		   Interface to print the help 
-		   \param os output stream to print to
-		*/
-		virtual void print(std::ostream& os) const = 0;
-	};
-
-	/** Constructor of the command option
-	     \param cb callback to call when help option is requested
-	     \param short_opt short option name (or 0)
-	     \param long_opt long option name (must not be NULL)
-	     \param long_help long help string (must not be NULL)
-         */
-	CHelpOption(Callback *cb, char short_opt, const char*long_opt, const char *long_help);
-
-	/** Print the option to a stream 
-	    @param os 
-	*/
-	void print(std::ostream& os) const;
-
-private:
-	std::unique_ptr<Callback> m_callback;
-	virtual bool do_set_value(const char *str_value);
-	virtual size_t do_get_needed_args() const;
-	virtual void do_write_value(std::ostream& os) const;
-	virtual void do_get_long_help(std::ostream& os) const;
-	virtual void do_get_long_help_xml(std::ostream& os, xmlpp::Element& parent, 
-					  HandlerHelpMap& /*handler_map*/) const; 
-
-};
-
-/**
-    \ingroup cmdline
-    \brief Help callback to print the help for the given plug-in 
-  
-*/
-template <typename PluginHandler>
-class TPluginHandlerHelpCallback: public CHelpOption::Callback {
-	void print(std::ostream& os) const{
-		PluginHandler::instance().print_help(os);
-	}
-}; 
-
-
-/**
-   \ingroup cmdline
    \brief The class to hold the list of options
 
    This class holds all the user defined and default command line option, 
@@ -239,7 +177,8 @@ public:
 		hr_help_xml,  /**< XML-formatted help has been requested */
 		hr_usage,     /**< a short usage description has been requested */ 
 		hr_version,   /**< The version information has been requested */ 
-		hr_copyright  /**< The long copyright information has been requested */
+		hr_copyright, /**< The long copyright information has been requested */
+		hr_selftest   /**< The selftest was run */
 	};
 
         /**
@@ -264,6 +203,17 @@ public:
         */
 	void add(const std::string& group, PCmdOption opt);
 
+	/**
+	   Add a selftest option. 
+
+	   The selftest option runs the given self test and then exists. Additional parameters 
+	   given on the command line are ignored. 
+	   The option is set within the group \a Test and provides the long optionb name \a --selftest. 
+	   \param [out] test_result stores the result returned by running by running the test suite 
+	   \param callback the test functor that must have CSelftestCallback as a base class 
+	 */
+	void add_selftest(int& test_result, CSelftestCallback *callback);
+
         /** the work routine, can take the arguemnts straight from \a main
 	    This version parses the command line and allows for additional arguments that can be 
 	    read by get_remaining(). 
@@ -326,6 +276,11 @@ public:
 	   \param os new output stream
 	 */
 	void set_logstream(std::ostream& os); 
+
+
+	/** This function sets a flag that indicates that data written 
+	    to stdout is an actual result */
+	void set_stdout_is_result(); 
 private:
 	EHelpRequested do_parse(size_t argc, const char *args[], bool has_additional, 
 				const CPluginHandlerBase *additional_help) 
@@ -659,11 +614,13 @@ PCmdOption make_opt(std::vector<T>& value, const char *long_opt, char short_opt,
    \param long_opt long option name (must not be NULL)
    \param short_opt short option name (or 0)
    \param help help string (must not be NULL)
+   \param flags option flags
    \returns the option warped into a \a boost::shared_ptr
 
 */
 
-PCmdOption make_opt(bool& value, const char *long_opt, char short_opt, const char *help); 
+PCmdOption make_opt(bool& value, const char *long_opt, char short_opt, const char *help, 
+		    CCmdOptionFlags flags = CCmdOptionFlags::none); 
 
 /**
    \ingroup cmdline
@@ -817,19 +774,6 @@ PCmdOption make_opt(typename std::unique_ptr<T>& value, const char *default_valu
 }
 
 
-/**
-   \ingroup cmdline
-   \brief Create a command line help option 
-   
-   Create a command line hoption that is used to print out some help. 
-   \param long_opt long option name
-   \param short_opt short option char, set to 0 of none givn
-   \param long_help the help string for thie option
-   \param cb a call back that us used to write the help 
-*/
-PCmdOption  make_help_opt(const char *long_opt, char short_opt, 
-				     const char *long_help, CHelpOption::Callback* cb); 
-
 NS_MIA_END
 
 #endif
diff --git a/mia/core/cmdoption.cc b/mia/core/cmdoption.cc
index 005b727..5ae9bcf 100644
--- a/mia/core/cmdoption.cc
+++ b/mia/core/cmdoption.cc
@@ -32,21 +32,6 @@ using std::invalid_argument;
 NS_MIA_BEGIN
 
 CCmdOption::CCmdOption(char short_opt, const char *long_opt, 
-		       const char *long_help, const char *short_help, bool required):
-	m_short_opt(short_opt), 
-	m_long_opt(long_opt),
-	m_long_help(long_help), 
-	m_short_help(short_help),
-	m_flags(required ? CCmdOptionFlags::required : CCmdOptionFlags::none)
-{
-	TRACE_FUNCTION; 
-	cvdebug() << "Create option '" << long_opt << "'\n"; 
-        assert(long_opt);
-        assert(long_help);
-
-}
-
-CCmdOption::CCmdOption(char short_opt, const char *long_opt, 
 		       const char *long_help, const char *short_help, CCmdOptionFlags flags):
 	m_short_opt(short_opt), 
 	m_long_opt(long_opt),
@@ -238,7 +223,6 @@ void CCmdOption::add_option_xml(xmlpp::Element& parent, HandlerHelpMap& handler_
 	auto option = parent.add_child("option"); 
 	option->set_attribute("short", to_string<char>(get_short_option()));
 	option->set_attribute("long", get_long_option());
-	option->set_attribute("required", to_string<bool>(is_required())); 
 	option->set_attribute("default", get_value_as_string()); 
 	
 	auto flagstring = get_flag_string(); 
@@ -258,6 +242,9 @@ string CCmdOption::get_flag_string()const
 		ss << "output "; 
         if (mia::has_flag(m_flags, CCmdOptionFlags::required))
 		ss << "required ";
+        if (mia::has_flag(m_flags, CCmdOptionFlags::nonipype))
+		ss << "nonipype ";
+
 	return ss.str(); 
 }
 
diff --git a/mia/core/cmdoption.hh b/mia/core/cmdoption.hh
index b9adedd..93ad177 100644
--- a/mia/core/cmdoption.hh
+++ b/mia/core/cmdoption.hh
@@ -56,12 +56,9 @@ public:
 	    \param long_opt the long option name
 	    \param long_help a long help string
 	    \param short_help help to print out when only usage information is requested 
-	    \param required set to true if the option must be set by the user 
+	    \param flags add certain \a CCmdOptionFlags to the option 
         */
 	CCmdOption(char short_opt, const char *long_opt, const char *long_help, 
-		   const char *short_help, bool required)__attribute__((deprecated));
-
-	CCmdOption(char short_opt, const char *long_opt, const char *long_help, 
 		   const char *short_help, CCmdOptionFlags flags);
 	
 
diff --git a/mia/core/cmdoptionflags.hh b/mia/core/cmdoptionflags.hh
index 3c615c2..327a5c9 100644
--- a/mia/core/cmdoptionflags.hh
+++ b/mia/core/cmdoptionflags.hh
@@ -27,12 +27,13 @@ NS_MIA_BEGIN
 
 enum class CCmdOptionFlags : int {
         none = 0, 
-        required = 1, 
-        input = 2, 
+	required = 1, 
+	input = 2, 
         output = 4, 
         required_input = 3, 
 	required_output = 5,
-	validate = 8	
+	validate = 8, 	
+        nonipype = 16
 }; 
 
 inline CCmdOptionFlags operator | (CCmdOptionFlags lhs, CCmdOptionFlags rhs) 
@@ -66,7 +67,7 @@ inline std::ostream& operator << (std::ostream& os, CCmdOptionFlags flags)
         case CCmdOptionFlags::required_input: os << "CCmdOptionFlags::required_input"; break; 
         case CCmdOptionFlags::required_output: os << "CCmdOptionFlags::required_output"; break; 
         case CCmdOptionFlags::validate: os << "CCmdOptionFlags::validate"; break; 
-
+	case CCmdOptionFlags::nonipype: os << "CCmdOptionFlags::nonipype"; break; 
         default: os << "CCmdOptionFlags::<undefined>"; 
         }; 
         return os; 
diff --git a/mia/core/handler.hh b/mia/core/handler.hh
index 8468c97..273bab2 100644
--- a/mia/core/handler.hh
+++ b/mia/core/handler.hh
@@ -86,6 +86,12 @@ public:
 	/// \returns the behind-end  iterator to the plug-ins
 	const_iterator end()const; 
 
+	/**
+	   Add a given plug-in to the handler. The pointer must not be freed in client code. 
+	   @param plugin 
+	*/
+	void add_plugin(Interface *plugin); 
+
 protected: 
 	//! \name Constructors
         //@{
@@ -105,12 +111,6 @@ protected:
 	typename TPluginHandler<I>::Interface *plugin(const char *plugin) const;
 
 
-	/**
-	   Add a given plug-in to the handler 
-	   @param plugin 
-	 */
-	void add_plugin(Interface *plugin); 
-
 	void initialise(CPathNameArray searchpath); 
 
 private: 
diff --git a/mia/core/minimizer/gdas.cc b/mia/core/minimizer/gdas.cc
index e53814c..e0ab822 100644
--- a/mia/core/minimizer/gdas.cc
+++ b/mia/core/minimizer/gdas.cc
@@ -95,7 +95,7 @@ int CGDSAMinimizer::do_run(CDoubleVector& x)
                         tries = 0; 
                         copy(xwork.begin(), xwork.end(), x.begin()); 
                         
-                        if ( (f < 0.5 * f_old) && (step > m_max_step)) {
+                        if ( (f < 0.5 * f_old) && (step < m_max_step)) {
                                 step *= 1.5; 
                                 if (step > m_max_step) 
                                         step = m_max_step; 
@@ -114,8 +114,11 @@ int CGDSAMinimizer::do_run(CDoubleVector& x)
                                  << ", gmax = " << gmax << ", step=" << step << "\n"; 
                         
                         if (step > m_min_step) {
-                                // restore last solution 
-                                copy(x.begin(), x.end(), xwork.begin()); 
+				
+                                // restore last solution if current value larger 
+				if (f > f_old) 
+					copy(x.begin(), x.end(), xwork.begin()); 
+				
                                 step /= 2.0; 
                                 if (step < m_min_step)  
                                         step = m_min_step; 
diff --git a/mia/core/parameter.cc b/mia/core/parameter.cc
index 0df6019..a02794f 100644
--- a/mia/core/parameter.cc
+++ b/mia/core/parameter.cc
@@ -55,12 +55,14 @@ void CParameter::get_help_xml(xmlpp::Element& param) const
 {
 	TRACE_FUNCTION; 
 	param.set_attribute("type", m_type); 
-	param.set_attribute("required", to_string<bool>(m_is_required)); 
 	param.set_attribute("default", get_default_value());
 	ostringstream d; 
-//	descr(d); 
 	param.set_child_text(m_descr);
 	do_get_help_xml(param); 
+	if (m_is_required) {
+		auto flags = param.add_child("flags"); 
+		flags->set_child_text("required");
+	}
 }
 
 void CParameter::do_get_help_xml(xmlpp::Element& /*param*/) const
diff --git a/mia/2d/test_combiner.cc b/mia/core/selftestcmdoption.cc
similarity index 55%
copy from mia/2d/test_combiner.cc
copy to mia/core/selftestcmdoption.cc
index ebf7895..890c199 100644
--- a/mia/2d/test_combiner.cc
+++ b/mia/core/selftestcmdoption.cc
@@ -18,26 +18,23 @@
  *
  */
 
-#include <stdexcept>
-#include <climits>
+#include <cassert>
+#include <mia/core/selftestcmdoption.hh>
+#include <mia/core/plugin_base.hh>
 
-#include <mia/internal/autotest.hh>
-#include <boost/filesystem/path.hpp>
-#include <mia/2d/filter.hh>
+NS_MIA_BEGIN
 
+CSelftestCallback::CSelftestCallback(int argc, char **argv):
+        m_argc(argc), m_argv(argv)
+{
+}
+        
+int CSelftestCallback::run () const
+{
+        PrepareTestPluginPath prepare_plugin_path; 
+        return do_run(m_argc, m_argv); 
+}
 
-NS_MIA_USE
-using namespace boost;
-using namespace std;
-namespace bfs=boost::filesystem; 
 
-BOOST_AUTO_TEST_CASE( test_load_plugins ) 
-{	
-	CPathNameArray plugpath;
-	plugpath.push_back(bfs::path("combiner"));
-	C2DImageCombinerPluginHandler::set_search_path(plugpath);
 
-	const C2DImageCombinerPluginHandler::Instance& handler = C2DImageCombinerPluginHandler::instance(); 
-	BOOST_CHECK_EQUAL(handler.size(), 5u); 
-	BOOST_CHECK_EQUAL(handler.get_plugin_names(), "absdiff add div mul sub ");
-}
+NS_MIA_END
diff --git a/mia/core/selftestcmdoption.hh b/mia/core/selftestcmdoption.hh
new file mode 100644
index 0000000..c9ddaec
--- /dev/null
+++ b/mia/core/selftestcmdoption.hh
@@ -0,0 +1,89 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef mia_core_selftestcmdoption_hh
+#define mia_core_selftestcmdoption_hh
+
+#include <mia/core/cmdoption.hh>
+#include <memory>
+
+NS_MIA_BEGIN
+
+/**
+   The base class for the selftest callback. 
+
+   The self test class provides the interface to add a selftest option 
+   that invokes the tests for normal programs. 
+   
+   For a working implementation the abstract method 
+ 
+   int do_run(int argc, char **argv) const; 
+ 
+   must be overridden. It must return zero if the tests pass and non-zero if they don't. 
+*/
+struct EXPORT_CORE CSelftestCallback {
+        /**
+           Constructor of the callback function. Usually you can just inherit it 
+           by the C++11 "using Callback::Callback" directive. 
+           
+           \param argc number of following arguments 
+           \param argv an array of string arguments
+        */
+        CSelftestCallback(int argc, char **argv); 
+        
+ private: 
+        friend class CSelftestOption; 
+        
+        /** runs the test suite 
+            \returns 0 if all tests were successfull and non-zero otherwise
+        */
+        int run() const; 
+        
+        /**
+           Interface for the callback function to be overridden.
+        */
+        virtual int do_run(int argc, char **argv) const = 0; 
+        
+        int m_argc; 
+        char **m_argv; 
+}; 
+
+/**
+   This define creates an derived selftest class that runs a BOOST test suite. 
+   As usual, the boost tests have to be defined by using BOOST_*_TEST_CASE. 
+   
+   In order to use this test case an instance of this class created with \a new 
+   must be passed to the command line parser by using the add_selftest method.
+   \param NAME name of the selftest class. 
+   
+ */
+#define SELFTEST_CALLBACK(NAME)  class NAME: public CSelftestCallback { \
+        public:                                                         \
+        using CSelftestCallback::CSelftestCallback;                     \
+                                                                        \
+        private:                                                        \
+        int do_run(int argc, char **argv)const {                        \
+                return ::boost::unit_test::unit_test_main( &init_unit_test, argc, argv); \
+        }                                                               \
+}
+
+NS_MIA_END
+
+#endif 
diff --git a/mia/core/statistics.hh b/mia/core/statistics.hh
index 96ac893..89987f7 100644
--- a/mia/core/statistics.hh
+++ b/mia/core/statistics.hh
@@ -110,7 +110,7 @@ FMedianMAD::result_type FMedianMAD::operator()( const T& data) const
 	result.first = median(buffer); 
 
 	transform(buffer.begin(), buffer.end(), buffer.begin(), 
-		  [&result](double x) {return abs(x - result.first);});
+		  [&result](double x) {return fabs(x - result.first);});
 	result.second = median(buffer); 
 	return result; 
 }
diff --git a/mia/core/test_attributes.cc b/mia/core/test_attributes.cc
index 905496e..006bc68 100644
--- a/mia/core/test_attributes.cc
+++ b/mia/core/test_attributes.cc
@@ -120,8 +120,8 @@ BOOST_AUTO_TEST_CASE( test_translator )
 
 
 	check_translate_type("bit", true, "1");
-	check_translate_type("double", 1.9, "1.9");
-	check_translate_type("float", 1.7f, "1.7");
+	check_translate_type("double", 1.8, "1.8");
+	check_translate_type("float", 1.75f, "1.75");
 	check_translate_type("ubyte", (unsigned char)129, "129");
 	check_translate_type("sbyte", (signed char)-120, "-120");
 	check_translate_type("sshort", (signed short)-1231, "-1231");
diff --git a/miacore.pc.cmake b/miacore.pc.cmake
index d2c9fda..050befb 100644
--- a/miacore.pc.cmake
+++ b/miacore.pc.cmake
@@ -8,10 +8,13 @@ includedir=${prefix}/@INCLUDE_INSTALL_PATH@
 pluginroot=@PLUGIN_SEARCH_PATH@
 TestLibs= 
 
+doctools=@MIA_DOCTOOLS_INSTALL_ROOT@
+
 Name: miacore
 Description: A library for 2D/3D grayscale image processing 
 Version: @PACKAGE_VERSION@
 Conflicts:
+Requires: libxml++-2.6
 Requires.private: @PKG_CONFIG_DEPS@ 
 Libs: -lmiacore- at VERSION@  -L${prefix}/@LIBRARY_INSTALL_PATH@ -lboost_system 
 Cflags: -I${prefix}/@INCLUDE_INSTALL_PATH@ -I at LIB_INCLUDE_INSTALL_PATH@
diff --git a/src/2davgmasked.cc b/src/2davgmasked.cc
index 3c3bcad..c91aa1e 100644
--- a/src/2davgmasked.cc
+++ b/src/2davgmasked.cc
@@ -104,7 +104,7 @@ int do_main( int argc, char *argv[] )
 			      CCmdOptionFlags::required_input, &image2dio));
 	options.add(make_opt( mask_filename, "mask-file", 'm', "mask image, must be of type byte", 
 			      CCmdOptionFlags::required_input, &image2dio));
-
+	options.set_stdout_is_result();
 	if (options.parse(argc, argv, "image") != CCmdOptionList::hr_no) 
 		return EXIT_SUCCESS; 
 
diff --git a/src/2dcost.cc b/src/2dcost.cc
index fa92a10..e00830b 100644
--- a/src/2dcost.cc
+++ b/src/2dcost.cc
@@ -45,11 +45,13 @@ int do_main(int argc, char **argv)
 {
 
 	CCmdOptionList options(g_description);
-
+	options.set_stdout_is_result();
+	
 	if (options.parse(argc, argv, "cost", &C2DFullCostPluginHandler::instance()) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 
 
+	
 	auto cost_chain = options.get_remaining();
 
 	if (cost_chain.empty()) {
diff --git a/src/2ddistance.cc b/src/2ddistance.cc
index e81f755..db67d4a 100644
--- a/src/2ddistance.cc
+++ b/src/2ddistance.cc
@@ -52,6 +52,7 @@ const SProgramDescription g_general_help = {
 
 enum EOps {dist_avg, 
 	   dist_max, 
+	   dist_raw, 
 	   dist_unknown
 }; 
 
@@ -59,6 +60,7 @@ enum EOps {dist_avg,
 const TDictMap<EOps>::Table combine_option_table[] = {
 	{"avg", dist_avg, "use average"},
 	{"max", dist_max, "use maximum" },
+	{"raw", dist_raw, "collect raw values as vector" },
 	{NULL, dist_unknown, ""},
 };
 
@@ -71,14 +73,14 @@ class Convert2DoubleAndScale: public TFilter<C2DDImage>{
 	C2DDImage operator ()(const T2DImage<T>& image) const {
 		C2DDImage result(image.get_size()); 
 		transform(image.begin(), image.end(),  result.begin(), 
-			  [this](T x){return x/_M_scale;}); 
+			  [this](T x){return x * _M_scale;}); 
 		return result; 
 	}
 private:
 	double _M_scale; 
 };
 
-class CGetDistance: public TFilter<double> {
+class CGetDistance: public TFilter<vector<double>> {
 public: 
 	CGetDistance(const C2DDImage& dist_field, EOps method): 
 		_M_distance(dist_field),
@@ -93,6 +95,7 @@ public:
 		auto d = _M_distance.begin(); 
 		auto i = image.begin(); 
 		auto e = image.end(); 
+		vector<double> vresult; 
 
 		switch (_M_method) {
 		case dist_avg: {
@@ -106,7 +109,8 @@ public:
 				++d; 
 				++i; 
 			}
-			return n == 0 ? 0 : result / n; 
+			vresult.push_back(n == 0 ? 0 : result / n); 
+			return vresult; 
 		}
 		case dist_max: {
 			double result = 0.0; 
@@ -117,7 +121,17 @@ public:
 				++d; 
 				++i; 
 			}
-			return result; 
+			vresult.push_back(result); 
+			return vresult; 
+		}
+		case dist_raw: {
+			while (i != e) {
+				if (*i) 
+					vresult.push_back(*d); 
+				++d; 
+				++i; 
+			}
+			return vresult; 
 		}
 		default: 
 			throw runtime_error("unknown distance measure requested\n"); 
@@ -133,6 +147,7 @@ int do_main( int argc, char *argv[] )
 
 	string in_filename;
 	string dist_filename;
+	string out_filename("-");
 	float scale = 1.0; 
 	EOps method = dist_avg; 
 	
@@ -144,7 +159,9 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt( in_filename, "in-file", 'i', "input image", 
 			      CCmdOptionFlags::required_input, &imageio)); 
 	options.add(make_opt( dist_filename, "distance-file", 'd', "distance field image (floating point)", 
-			      CCmdOptionFlags::required_output, &imageio)); 
+			      CCmdOptionFlags::required_input, &imageio)); 
+	options.add(make_opt(out_filename, "out-file", 'o', "output file, '-': write to stdout", CCmdOptionFlags::required_output)); 
+
 	options.add(make_opt( scale, "scale", 's', "distance scaling factor")); 
 	options.add(make_opt( method, combine_option, "method", 'm', "distance measuring method")); 
 	
@@ -160,7 +177,15 @@ int do_main( int argc, char *argv[] )
 	C2DDImage dist = mia::filter(create_dist, *dist_image); 
 	
 	CGetDistance get_distance(dist, method); 
-	cout << filter(get_distance, *in_image) <<"\n";
+	auto result = filter(get_distance, *in_image); 
+	if (out_filename == "-") 
+		cout << result <<"\n";
+	else {
+		ofstream out(out_filename.c_str()); 
+		out << result; 
+		if (!out.good())
+			create_exception<runtime_error>("Error writing result to '", out_filename, "'"); 
+	}
 	return EXIT_SUCCESS; 
 }
 
diff --git a/src/2dgrayimage-combine-to-rgb.cc b/src/2dgrayimage-combine-to-rgb.cc
index 3498ca9..ca75501 100644
--- a/src/2dgrayimage-combine-to-rgb.cc
+++ b/src/2dgrayimage-combine-to-rgb.cc
@@ -94,7 +94,7 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt( red_filename, "red", 'r', "input image for red channel", 
 			      CCmdOptionFlags::input, &imageio));
 
-	options.add(make_opt( out_filename, "out-file", 'o', "combined output image", CCmdOptionFlags::required_input, &imageio));
+	options.add(make_opt( out_filename, "out-file", 'o', "combined output image", CCmdOptionFlags::required_output, &imageio));
 	
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS;
diff --git a/src/2dimagecombine-dice.cc b/src/2dimagecombine-dice.cc
index fd36e58..d077581 100644
--- a/src/2dimagecombine-dice.cc
+++ b/src/2dimagecombine-dice.cc
@@ -92,7 +92,7 @@ int do_main( int argc, char *argv[] )
 			      CCmdOptionFlags::required_input, &imageio)); 
 	options.add(make_opt( in_filename2, "in-file-2", '2', "input image 2", 
 			      CCmdOptionFlags::required_input, &imageio)); 
-
+	options.set_stdout_is_result();
 	
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
diff --git a/src/2dimagefilter.cc b/src/2dimagefilter.cc
index 847e884..e8d75ef 100644
--- a/src/2dimagefilter.cc
+++ b/src/2dimagefilter.cc
@@ -54,10 +54,6 @@ int do_main( int argc, char *argv[] )
 			      CCmdOptionFlags::required_input, &imageio));
 	options.add(make_opt( out_filename, "out-file", 'o', "output image(s) that have been filtered", 
 			      CCmdOptionFlags::required_output, &imageio));
-	options.set_group(g_help_optiongroup); 
-	options.add(make_help_opt( "help-filters", 0,
-				   "give some help about the filter plugins", 
-				   new TPluginHandlerHelpCallback<C2DFilterPluginHandler>));
 	
 	if (options.parse(argc, argv, "filter", &filter_plugins) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
diff --git a/src/2dimagefilterstack.cc b/src/2dimagefilterstack.cc
index 4d0ea07..5a4eb56 100644
--- a/src/2dimagefilterstack.cc
+++ b/src/2dimagefilterstack.cc
@@ -83,12 +83,6 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt(startid, "start", 's', "first possible number of file number range to be filtered")); 
 	options.add(make_opt(endid, "end", 'e', "last possible number of file number range to be filtered")); 
 	
-		
-	options.set_group(g_help_optiongroup); 
-	options.add(make_help_opt( "help-filters", 0,
-				   "give some help about the filter plugins", 
-				   new TPluginHandlerHelpCallback<C2DFilterPluginHandler>)); 
-		
 	if (options.parse(argc, argv, "filter", &filter_plugins) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 		
diff --git a/src/2dimagefullstats.cc b/src/2dimagefullstats.cc
index 35aceb3..f5c703f 100644
--- a/src/2dimagefullstats.cc
+++ b/src/2dimagefullstats.cc
@@ -52,6 +52,7 @@ int do_main( int argc, char *argv[] )
 
 	string in_filename;
 	CCmdOptionList options(g_general_help);
+	options.set_stdout_is_result();
 	options.add(make_opt( in_filename, "in-file", 'i', "input image", 
 			      CCmdOptionFlags::required_input, &C2DImageIOPluginHandler::instance()));
 	
diff --git a/src/2dimageregistration.cc b/src/2dimageregistration.cc
index a4eb449..e81d13d 100644
--- a/src/2dimageregistration.cc
+++ b/src/2dimageregistration.cc
@@ -56,10 +56,10 @@ int do_main( int argc, char *argv[] )
 	CCmdOptionList options(g_general_help);
 	
 	options.set_group("File-IO"); 
-	options.add(make_opt( src_filename, "in", 'i', "test image", CCmdOptionFlags::required_input, &imageio));
-	options.add(make_opt( ref_filename, "ref", 'r', "reference image", CCmdOptionFlags::required_input, &imageio));
-	options.add(make_opt( out_filename, "out", 'o', "registered output image", CCmdOptionFlags::output, &imageio));
-	options.add(make_opt( trans_filename, "trans", 't', "output transformation", 
+	options.add(make_opt( src_filename, "in-image", 'i', "test image to be registered", CCmdOptionFlags::required_input, &imageio));
+	options.add(make_opt( ref_filename, "ref-image", 'r', "reference image to be registered to", CCmdOptionFlags::required_input, &imageio));
+	options.add(make_opt( out_filename, "out-image", 'o', "registered output image", CCmdOptionFlags::output, &imageio));
+	options.add(make_opt( trans_filename, "transformation", 't', "output transformation comprising the registration",
 			      CCmdOptionFlags::required_output, &C2DTransformationIOPluginHandler::instance()));
 
 	options.set_group("Parameters"); 
diff --git a/src/2dimagestats.cc b/src/2dimagestats.cc
index fad4618..1decee1 100644
--- a/src/2dimagestats.cc
+++ b/src/2dimagestats.cc
@@ -104,6 +104,7 @@ int do_main( int argc, char *argv[] )
 			      CCmdOptionFlags::required_input, &imageio));
 	options.add(make_opt( thresh, "thresh", 't', "intensity thresh to ignore"));
 	options.add(make_opt( high_thresh, "high-thresh", 'g', "upper histogram percentage to ignore"));
+	options.set_stdout_is_result();
 	
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
diff --git a/src/2dlerp.cc b/src/2dlerp.cc
index e16cf62..8df5d50 100644
--- a/src/2dlerp.cc
+++ b/src/2dlerp.cc
@@ -19,6 +19,10 @@
  */
 
 #include <climits>
+
+#define BOOST_TEST_MAIN
+#define BOOST_TEST_NO_MAIN
+
 #include <boost/test/unit_test_suite.hpp>
 #include <boost/test/unit_test.hpp>
 #include <boost/test/floating_point_comparison.hpp>
@@ -39,7 +43,9 @@ const SProgramDescription g_description = {
 	{pdi_short, "Linearly combine two 2D images."}, 
 	{pdi_description, "Merge two images by pixel-wise linearly combining their intensities."}, 
 	{pdi_example_descr, "Combine image inputA.v and inputB.v by using position coordinates "
-	 "4, 7, and 9 and write the result to output.v"}, 
+	 "4, 7, and 9. This means the output pixel values will be evaluated according to\n\n"
+	 "    (9-7)/(9-4) * A + (7-4)/(9-4) * B  \n\n"
+	 "The result image will be written to output.v"},
 	{pdi_example_code, "-1 inputA.v -2 inputB.v -p 4,7,9 -o output.v"}
 }; 
 
@@ -79,8 +85,9 @@ private:
 	float m_w;
 };
 
-static void run_self_test()
+BOOST_AUTO_TEST_CASE ( run_self_test )
 {
+	
 	const C2DBounds size(1,2);
 	
 	C2DFImage *A = new C2DFImage(size);
@@ -105,12 +112,8 @@ static void run_self_test()
 	
 }
 
-static bool init_unit_test_suite( )
-{
-	::boost::unit_test::framework::master_test_suite().add( BOOST_TEST_CASE( &run_self_test));
-	return true;
-}
 
+     
 template <typename F>
 struct FFilter {
 	FFilter(const F& f):
@@ -125,6 +128,8 @@ private:
 	const F& m_f;
 };
 
+SELFTEST_CALLBACK(CSelftest);
+
 int do_main(int argc, char **argv)
 {
 
@@ -132,7 +137,7 @@ int do_main(int argc, char **argv)
 	string src1_filename;
 	string src2_filename;
 	string out_filename;
-	bool self_test = false;
+	int self_test_result = 0;
 
 	vector<float> positions;
 
@@ -147,15 +152,17 @@ int do_main(int argc, char **argv)
 	options.add(make_opt( positions, "positions", 'p', 
 			      "image series positions (first, target, second)", 
 			      CCmdOptionFlags::required));
-	options.add(make_opt( self_test, "self-test", 0, "run a self test of the tool"));
+	options.add_selftest(self_test_result, new CSelftest(argc, argv));
 	
-	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
+	switch (options.parse(argc, argv, "boost-test-options")) {
+	case CCmdOptionList::hr_no:
+		break; 
+	case CCmdOptionList::hr_selftest: 
+		return self_test_result; 
+	default: 
 		return EXIT_SUCCESS; 
-
-	if (self_test) {
-		return ::boost::unit_test::unit_test_main( &init_unit_test_suite, argc, (char **)argv );
 	}
-
+	
 	if (positions.size() != 3) {
 		stringstream msg;
 		msg << "positions must be 3 values: first, target, second, got " << positions.size() << "images";
diff --git a/src/2dmany2one-nonrigid.cc b/src/2dmany2one-nonrigid.cc
index 45dc3db..52e0465 100644
--- a/src/2dmany2one-nonrigid.cc
+++ b/src/2dmany2one-nonrigid.cc
@@ -142,7 +142,7 @@ int do_main( int argc, char *argv[] )
 			      "input perfusion data set", CCmdOptionFlags::required_input));
 	options.add(make_opt( registered_filebase, "out-file", 'o', 
 			      "file name for registered images, numbering and pattern are deducted from the input data", 
-			      CCmdOptionFlags::required)); 
+			      CCmdOptionFlags::required_output)); 
 	
 	options.set_group("\nRegistration"); 
 	options.add(make_opt( minimizer, "optimizer", 'O', "Optimizer used for minimization"));
diff --git a/src/2dmulti-force.cc b/src/2dmulti-force.cc
index a3f6c4b..bf82ac8 100644
--- a/src/2dmulti-force.cc
+++ b/src/2dmulti-force.cc
@@ -24,6 +24,7 @@
 #include <sstream>
 #include <iomanip>
 #include <boost/algorithm/minmax_element.hpp>
+#include <mia/2d/transformfactory.hh>
 
 NS_MIA_USE
 using namespace boost;
@@ -37,10 +38,11 @@ const SProgramDescription g_description = {
 	 "The input images must be of the same dimensions and gray scale (whatever bit-depth)."}, 
 	{pdi_example_descr, "Evaluate the force normimage weighted sum of costs SSD and NGF of "
 	 "image1.v and image2.v. and store the result to force.v."}, 
-	{pdi_example_code, "-o force.v ssd:src=image1.v,ref=image2.v,weight=0.1 "
-	 "ngf:src=image1.v,ref=image2.v,weight=2.0"}
+	{pdi_example_code, "-o force.v image:cost=ssd,src=image1.v,ref=image2.v,weight=0.1 "
+	 "image:cost=ngf,src=image1.v,ref=image2.v,weight=2.0"}
 }; 
 
+
 struct FGetNorm  {
 	float operator ()(const C2DFVector& x) const {
 		return x.norm();
@@ -58,7 +60,7 @@ int do_main(int argc, char **argv)
 	const auto& imageio = C2DImageIOPluginHandler::instance();
 	const auto& costcreator = C2DFullCostPluginHandler::instance(); 
 
-	options.add(make_opt( out_filename, "out-file", 'o', "output norm image", CCmdOptionFlags::required_input, &imageio));
+	options.add(make_opt( out_filename, "out-file", 'o', "output norm image", CCmdOptionFlags::required_output, &imageio));
 
 	if (options.parse(argc, argv, "cost", &costcreator) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
@@ -71,23 +73,40 @@ int do_main(int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
-	C2DImageFatCostList cost_list;
+
+	C2DFullCostList cost_list;
 	for(auto i = cost_chain.begin(); i != cost_chain.end(); ++i) {
-		P2DImageFatCost c = costcreator.produce(*i);
+		auto c = costcreator.produce(*i);
 		assert(c); 
-		cost_list.push_back(c);
+		cost_list.push(c);
 	}
 
-	C2DFVectorfield force(cost_list.get_size());
-
+	cost_list.reinit(); 
+	C2DBounds size; 
+	if (!cost_list.get_full_size(size)) {
+		throw invalid_argument("Input images given for the cost functions are no of the same size"); 
+	}
+	cost_list.set_size(size); 
+	
 	if ( out_filename.empty()) {
-		cout <<  cost_list.value() << endl;
+		cout <<  cost_list.cost_value() << endl;
 		return EXIT_SUCCESS;
 	}
-
-	C2DFImage *result = new C2DFImage(force.get_size());
-
-	transform(force.begin(), force.end(), result->begin(), FGetNorm());
+	
+	auto tff = C2DTransformCreatorHandler::instance().produce("vf:imgkernel=[bspline:d=0],imgboundary=zero"); 
+	auto t = tff->create(size); 
+	auto params = t->get_parameters(); 
+	std::fill(params.begin(), params.end(), 0.0); 
+	t->set_parameters(params); 
+
+	double cost_value = cost_list.evaluate(*t, params);
+
+	C2DFImage *result = new C2DFImage(size);
+	int i = 0; 
+	
+	for (auto ir = result->begin(); ir != result->end(); ++ir, i+=2){
+		*ir = sqrt(params[i] * params[i] + params[i+1] * params[i+1]); 
+	}
 
 	P2DImage norm_img(result);
 
@@ -97,11 +116,7 @@ int do_main(int argc, char **argv)
 	if (pts.find(it_float) == pts.end())
 		norm_img = C2DFilterPluginHandler::instance().produce("convert")->filter(*norm_img);
 
-	C2DImageIOPluginHandler::Instance::Data images;
-	images.push_back(norm_img);
-
-
-	if ( !imageio.save(out_filename, images) )
+	if ( !save_image(out_filename, norm_img) )
 		throw runtime_error(string("unable to save to: ") + out_filename);
 
 	return EXIT_SUCCESS;
diff --git a/src/2dmultiimageregistration.cc b/src/2dmultiimageregistration.cc
new file mode 100644
index 0000000..ac1258a
--- /dev/null
+++ b/src/2dmultiimageregistration.cc
@@ -0,0 +1,92 @@
+/* -*- mia-c++  -*-
+ *
+ * This file is part of MIA - a toolbox for medical image analysis 
+ * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
+ *
+ * MIA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIA; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sstream>
+#include <mia/core.hh>
+#include <mia/2d.hh>
+#include <mia/2d/nonrigidregister.hh>
+#include <mia/core/minimizer.hh>
+#include <mia/2d/transformfactory.hh>
+#include <mia/2d/transformio.hh>
+
+NS_MIA_USE;
+using namespace std;
+
+const SProgramDescription g_description = {
+	{pdi_group,  "Registration, Comparison, and Transformation of 2D images"}, 
+
+	{pdi_short,  "Non-linear registration of 2D images."},
+	
+	{pdi_description, "This program runs a non-rigid registration based on the given cost criteria "
+	 "and a given transformation model. Other than mia-2dnonrigidreg it doesn't support "
+	 "specific command line parameters to provide the images. Instead the images are specified "
+	 "dirctly when defining the cost function. Hence, image registrations can be executed that "
+	 "optimize the aligmnet of  more than one image pair at the same time. Note, however, that "
+	 "all input images must be of the same dimension (in pixels)"}, 
+	
+	{pdi_example_descr,
+	 "Register image test.v to image ref.v by using a spline transformation with a "
+	 "coefficient rate of 5  and write the registered image to reg.v. "
+	 "Use two multiresolution levels, ssd as image cost function and divcurl weighted by 10.0 "
+	 "as transformation smoothness penalty. The resulting transformation is saved in reg.vf."},
+
+	{pdi_example_code, "-o reg.vf -l 2 -f spline:rate=3,penalty=divcurl image:cost=ssd,src=test.v,ref=ref.v"}
+};
+
+
+int do_main( int argc, char *argv[] )
+{
+	string trans_filename;
+	size_t mg_levels = 3;
+	PMinimizer minimizer; 
+	P2DTransformationFactory transform_creator; 
+
+	const auto& transform2dio =  C2DTransformationIOPluginHandler::instance(); 
+
+	CCmdOptionList options(g_description);
+	options.add(make_opt( trans_filename, "out-transform", 'o', "output transformation", 
+			      CCmdOptionFlags::required_output, &transform2dio));
+	options.add(make_opt( mg_levels, "levels", 'l', "multi-resolution levels"));
+	options.add(make_opt( minimizer, "gsl:opt=gd,step=0.1", "optimizer", 'O', "Optimizer used for minimization"));
+	options.add(make_opt( transform_creator, "spline:rate=10,penalty=divcurl", "transForm", 'f', "transformation type"));
+	
+	if (options.parse(argc, argv, "cost", &C2DFullCostPluginHandler::instance()) != CCmdOptionList::hr_no)
+		return EXIT_SUCCESS; 
+
+	
+	auto cost_descrs = options.get_remaining(); 
+
+	C2DFullCostList costs; 
+	for (auto i = cost_descrs.begin(); i != cost_descrs.end(); ++i)
+		costs.push(C2DFullCostPluginHandler::instance().produce(*i)); 
+
+
+	C2DNonrigidRegister nrr(costs, minimizer,  transform_creator, mg_levels);
+	P2DTransformation transform = nrr.run();
+
+	if (! transform2dio.save(trans_filename, *transform) )
+		throw create_exception<runtime_error>("Unable to save obtained transformation to '", trans_filename, "'");
+	return EXIT_SUCCESS; 
+}
+
+
+
+#include <mia/internal/main.hh>
+MIA_MAIN(do_main)
diff --git a/src/2dmyocard-ica.cc b/src/2dmyocard-ica.cc
index 94243fe..ab11e91 100644
--- a/src/2dmyocard-ica.cc
+++ b/src/2dmyocard-ica.cc
@@ -366,7 +366,8 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt( src_name, "in-base", 'i', "input file name ofolloing pattern nameXXXX.ext X=numbers" , 
 			      CCmdOptionFlags::required_input, &imageio));
 	options.add(make_opt( coefs_name, "coefs", 0, "output mixing coefficients to this file"));
-	options.add(make_opt( out_name, "out-base", 'o', "output file name base"));
+	options.add(make_opt( out_name, "out-base", 'o', "output file name base", 
+			      CCmdOptionFlags::output));
 
 	options.add(make_opt( out_type, imageio.get_supported_suffix_set(), "type", 't',
 				    "output file type"));
diff --git a/src/2dmyocard-icaseries.cc b/src/2dmyocard-icaseries.cc
index 4d5e349..d5aa747 100644
--- a/src/2dmyocard-icaseries.cc
+++ b/src/2dmyocard-icaseries.cc
@@ -89,12 +89,12 @@ int do_main( int argc, char *argv[] )
 	options.set_group("File-IO"); 
 	options.add(make_opt( in_filename, "in-file", 'i', "input perfusion data set", CCmdOptionFlags::required_input));
 	options.add(make_opt( reference_filename, "references", 'r', "File name base for the reference images. "
-			      "Image type and numbering scheme are taken from the input images.")); 
+			      "Image type and numbering scheme are taken from the input images.", CCmdOptionFlags::output)); 
 	options.add(make_opt( cropped_filename, "save-cropped", 'c', "save cropped set of the original set to this file, "
-			      "the image files will use the stem of the name as file name base")); 
+			      "the image files will use the stem of the name as file name base", CCmdOptionFlags::output)); 
 	options.add(make_opt( save_crop_feature, "save-feature", 0, "save the features images resulting from the ICA and "
 			      "some intermediate images used for the RV-LV segmentation with the given file name base to PNG files. "
-			      "Also save the coefficients of the initial best and the final IC mixing matrix.")); 
+			      "Also save the coefficients of the initial best and the final IC mixing matrix.", CCmdOptionFlags::output)); 
 	
 	options.set_group("ICA");
 	options.add(make_opt( components, "components", 'C', "ICA components 0 = automatic estimation"));
diff --git a/src/2dmyoseries-compdice.cc b/src/2dmyoseries-compdice.cc
index 056d494..7afa835 100644
--- a/src/2dmyoseries-compdice.cc
+++ b/src/2dmyoseries-compdice.cc
@@ -75,6 +75,7 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt( org_filename, "first", '1', "first segmentation set", CCmdOptionFlags::required_input));
 	options.add(make_opt( ref_filename, "second", '2', "second segmentation set", CCmdOptionFlags::required_input));
 	options.add(make_opt( skip, "skip", 'k', "images to skip atthe begin of the series")); 
+	options.set_stdout_is_result();
 	
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
diff --git a/src/2dmyoseries-dice.cc b/src/2dmyoseries-dice.cc
index 1078847..cda9eb0 100644
--- a/src/2dmyoseries-dice.cc
+++ b/src/2dmyoseries-dice.cc
@@ -76,7 +76,7 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt( org_filename, "input", 'i', "original segmentation set", CCmdOptionFlags::required_input));
 	options.add(make_opt( skip, "skip", 'k', "images to skip atthe bgin of the series")); 
 	options.add(make_opt( reference, "reference", 'r', "reference image")); 
-	
+	options.set_stdout_is_result();
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 
diff --git a/src/2dsegcompare.cc b/src/2dsegcompare.cc
index 7a67f5f..c8adaf7 100644
--- a/src/2dsegcompare.cc
+++ b/src/2dsegcompare.cc
@@ -67,6 +67,8 @@ int do_main(int argc, char *argv[])
 	CCmdOptionList options(g_description);
 	options.add(make_opt( src_filename, "in-file", 'i', "input segmentation set", CCmdOptionFlags::required_input));
 	options.add(make_opt( ref_filename, "ref-file", 'r', "reference  segmentation set", CCmdOptionFlags::required_input));
+	options.set_stdout_is_result();
+	
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 
diff --git a/src/2dseghausdorff.cc b/src/2dseghausdorff.cc
index bb1de98..c400dfd 100644
--- a/src/2dseghausdorff.cc
+++ b/src/2dseghausdorff.cc
@@ -62,6 +62,7 @@ int do_main(int argc, char *argv[])
 	options.add(make_opt( src_filename, "in-file", 'i', "input segmentation set", CCmdOptionFlags::required_input));
 	options.add(make_opt( reference, "ref-frame", 'r', "reference frame", CCmdOptionFlags::required_input));
 	options.add(make_opt( skip, "skip", 'k', "skip frames at the beginning"));
+	options.set_stdout_is_result();
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 
diff --git a/src/2dsegseriesstats.cc b/src/2dsegseriesstats.cc
index 9630055..965ff09 100644
--- a/src/2dsegseriesstats.cc
+++ b/src/2dsegseriesstats.cc
@@ -125,8 +125,10 @@ int do_main( int argc, char *argv[] )
 			      "using the original segmentation of the reference on all images of the original series, "
 			      "the second column contains the values obtained by the registered segmentation of the "
 			      "reference on all images of the registered series, and the third column contains the "
-			      "values obtained by using the segmentations of each slice on the original images."));
-	options.add(make_opt( varcurves_filename, "varcurves", 'v', "region variation values, same formt as described above. "));
+			      "values obtained by using the segmentations of each slice on the original images.", 
+			      CCmdOptionFlags::output));
+	options.add(make_opt( varcurves_filename, "varcurves", 'v', "region variation values, same formt as described above. ", 
+			      CCmdOptionFlags::output));
 	options.add(make_opt( n_sections, "nsections", 'n', 
 			      "number of sections to use, 0=use as segmented, otherwise Otherwise, the LV myocardium is "
 			      "divided into n sections that enclose equal angles starting at the "
diff --git a/src/2dseries-mincorr.cc b/src/2dseries-mincorr.cc
index 1a42b56..b4a87b8 100644
--- a/src/2dseries-mincorr.cc
+++ b/src/2dseries-mincorr.cc
@@ -89,8 +89,8 @@ int do_main( int argc, char *argv[] )
 
 
 	CCmdOptionList options(g_description);
-	options.add(make_opt( src_name, "in", 'i', "input segmentation set", CCmdOptionFlags::required_input));
-	options.add(make_opt( out_name, "out", 'o', "output image of minimal correlation", 
+	options.add(make_opt( src_name, "in-set", 'i', "input segmentation set", CCmdOptionFlags::required_input));
+	options.add(make_opt( out_name, "out-set", 'o', "output image of minimal correlation", 
 			      CCmdOptionFlags::required_output,  &C2DImageIOPluginHandler::instance()));
 	options.add(make_opt( skip, "skip", 'k', "skip images at beginning of series"));
 
diff --git a/src/2dseries-segdistance.cc b/src/2dseries-segdistance.cc
index 5aff518..4824378 100644
--- a/src/2dseries-segdistance.cc
+++ b/src/2dseries-segdistance.cc
@@ -103,6 +103,9 @@ int do_main(int argc, char *argv[])
 	options.add(make_opt( src_filename, "in-file", 'i', "input segmentation set", CCmdOptionFlags::required_input));
 	options.add(make_opt( reference, "reference", 'r', "reference frame"));
 	options.add(make_opt( skip, "skip", 'k', "skip images at the beginning"));
+	
+	options.set_stdout_is_result();
+	
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 
diff --git a/src/2dseries2sets.cc b/src/2dseries2sets.cc
index 8421aff..266938c 100644
--- a/src/2dseries2sets.cc
+++ b/src/2dseries2sets.cc
@@ -171,7 +171,7 @@ int do_main( int argc, char *argv[] )
 	bool no_copy_images = false; 
 	
 	CCmdOptionList options(g_description);
-	options.add(make_opt( out_directory, "out", 'o', "output directory (needs to exist and be writable)", 
+	options.add(make_opt( out_directory, "out-directory", 'o', "output directory (needs to exist and be writable)", 
 			      CCmdOptionFlags::required_output));
 	options.add(make_opt( no_copy_images, "no-copy", 0, "don't copy image files to output directory"));
 
diff --git a/src/2dserieshausdorff.cc b/src/2dserieshausdorff.cc
index 623263d..a6bb371 100644
--- a/src/2dserieshausdorff.cc
+++ b/src/2dserieshausdorff.cc
@@ -60,6 +60,7 @@ int do_main(int argc, char *argv[])
 	options.add(make_opt( src_filename, "in-file", 'i', "input segmentation set", CCmdOptionFlags::required_input));
 	options.add(make_opt( ref_filename, "ref-file", 'r', "reference segmentation set", CCmdOptionFlags::required_input));
 	options.add(make_opt( skip, "skip", 'k', "skip images at the beginning"));
+	options.set_stdout_is_result();
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 
diff --git a/src/2dstackfilter.cc b/src/2dstackfilter.cc
index 64b3e95..60c6c31 100644
--- a/src/2dstackfilter.cc
+++ b/src/2dstackfilter.cc
@@ -123,12 +123,9 @@ int do_main(int argc, char *argv[])
 	options.add(make_opt( in_filename, "in-file", 'i', "input image(s) to be filtered", CCmdOptionFlags::required_input, &imageio));
 	options.add(make_opt( out_filename, "out-file", 'o', "output file name base, the actual names is created "
 			      "by adding the file number based on output order and the extension bysed on the 'type' parameter"
-			      , CCmdOptionFlags::required, &imageio));
+			      , CCmdOptionFlags::required_output, &imageio));
 	options.add(make_opt( out_type, imageio.get_supported_suffix_set(), "type", 't',
 			      "output file type", CCmdOptionFlags::required));
-	options.add(make_help_opt( "help-plugins", 0, 
-				   "give some help about the filter plugins", 
-				   new TPluginHandlerHelpCallback<C2DFifoFilterPluginHandler>)); 
 
 
 	if (options.parse(argc, argv, "filter", &sfh) != CCmdOptionList::hr_no)
diff --git a/src/3dcost.cc b/src/3dcost.cc
index af4f0fe..02a9c39 100644
--- a/src/3dcost.cc
+++ b/src/3dcost.cc
@@ -42,7 +42,7 @@ int do_main(int argc, char **argv)
 {
 
 	CCmdOptionList options(g_description);
-
+	options.set_stdout_is_result();
 	if (options.parse(argc, argv, "cost", &C3DFullCostPluginHandler::instance()) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 	
diff --git a/src/3ddistance-stats.cc b/src/3ddistance-stats.cc
index c864203..62f123a 100644
--- a/src/3ddistance-stats.cc
+++ b/src/3ddistance-stats.cc
@@ -185,10 +185,11 @@ int do_main( int argc, char *argv[] )
 			      CCmdOptionFlags::required_input, &imageio));
 
         options.add(make_opt( label_translate_filename, "label-map", 'l', "optional mapping of label numbers", 
-			    CCmdOptionFlags::input));
+			      CCmdOptionFlags::input));
 
         options.add(make_opt( out_filename, "out-file", 'o', "output file name to write the distances to. "
-                              "The output file is a csv file, containing distances listed for each label."));
+                              "The output file is a csv file, containing distances listed for each label.",
+			      CCmdOptionFlags::required_output));
         
 
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
diff --git a/src/3dfield2norm.cc b/src/3dfield2norm.cc
index 489802b..918e867 100644
--- a/src/3dfield2norm.cc
+++ b/src/3dfield2norm.cc
@@ -46,8 +46,10 @@ int do_main(int argc, char *argv[])
 	
 	CCmdOptionList options(g_description);
 	
-	options.add(make_opt( src_filename, "in", 'i', "input vector field", CCmdOptionFlags::required_input, &C3DVFIOPluginHandler::instance()));
-	options.add(make_opt( out_filename, "out", 'o', "output image", CCmdOptionFlags::required_output, &C3DImageIOPluginHandler::instance()));
+	options.add(make_opt( src_filename, "in-vectorfield", 'i', "input vector field", 
+			      CCmdOptionFlags::required_input, &C3DVFIOPluginHandler::instance()));
+	options.add(make_opt( out_filename, "out-image", 'o', "output image comprising the per voxel norm of each image", 
+			      CCmdOptionFlags::required_output, &C3DImageIOPluginHandler::instance()));
 
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
diff --git a/src/3dgetsize.cc b/src/3dgetsize.cc
index 218541c..c7e0c74 100644
--- a/src/3dgetsize.cc
+++ b/src/3dgetsize.cc
@@ -49,7 +49,7 @@ int do_main( int argc, char *argv[] )
 	CCmdOptionList options(g_description);
 	options.add(make_opt( in_filename, "in-file", 'i', "input image(s) to be filtered", 
 			      CCmdOptionFlags::required_input, &imageio3d));
-	
+	options.set_stdout_is_result();
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 	
diff --git a/src/3dgetslice.cc b/src/3dgetslice.cc
index 638ea04..5289c60 100644
--- a/src/3dgetslice.cc
+++ b/src/3dgetslice.cc
@@ -115,9 +115,13 @@ public:
 		bool retval = true;
 		for(size_t i = m_start; i < end; ++i) {
 			P2DImage pimage(new  T2DImage<T>(__dispatch<T, s_dir>::get_slice(i, image)));
-			stringstream out_name;
-			out_name << m_fname << setw(m_digits) << setfill('0') << i << "." << m_type;
-			retval &= save_image(out_name.str(), pimage);
+			if (m_n != 1) {
+				stringstream out_name;
+				out_name << m_fname << setw(m_digits) << setfill('0') << i << "." << m_type;
+				retval &= save_image(out_name.str(), pimage);
+			}else{
+				retval &= save_image(m_fname, pimage);
+			}
 		}
 		return retval;
 	}
@@ -136,7 +140,7 @@ int do_main( int argc, char *argv[] )
 	string out_filename;
 	string out_type("png");
 	size_t start_slice = 0;
-	size_t slice_number = 0;
+	size_t slice_number = 1;
 	EDirection direction = dir_xy;
 	int digits = 4; 
 
@@ -146,13 +150,14 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt( in_filename, "in-file", 'i', 
 			      "input image(s) to be filtered", 
 			      CCmdOptionFlags::required_input, &C3DImageIOPluginHandler::instance()));
-	options.add(make_opt( out_filename, "out-file", 'o', "output image(s) base name, give without "
-			      "extension since this will be based on the '--type' option", 
+	options.add(make_opt( out_filename, "out-file", 'o', "output image(s). If number != 1 than this is used as a base name "
+			      "and should be given without extension since this will be based on the '--type' option. "
+			      "If number=1 then this exact file name will be used.", 
 			      CCmdOptionFlags::required_output, &imageio2d));
-	options.add(make_opt( out_type, imageio2d.get_set(), "type", 't', "output file type"));
+	options.add(make_opt( out_type, imageio2d.get_set(), "type", 't', "output file type for number != 1"));
 	options.add(make_opt( start_slice, "start", 's',"start slice number"));
 	options.add(make_opt( slice_number, "number", 'n', "number of slices (all=0)"));
-	options.add(make_opt( digits, "ndigits", 0, "minimum number of digits of the file name numbers"));
+	options.add(make_opt( digits, "ndigits", 0, "minimum number of digits of the file name numbers (if n != 1)"));
 
 	options.add(make_opt( direction, GDirectionmap, "dir", 'd', 
 			      "slice direction (xy=axial, xz=coronal, yz=saggital)"));
diff --git a/src/3dimagecombine.cc b/src/3dimagecombine.cc
index e6c4cad..5c35f19 100644
--- a/src/3dimagecombine.cc
+++ b/src/3dimagecombine.cc
@@ -56,7 +56,7 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt( in_image2, "image2", '2', "input image  2 to be combined", 
 			      CCmdOptionFlags::required_input, &imageio));
 	options.add(make_opt( combiner, "add", "combiner", 'c', "combiner operation", CCmdOptionFlags::required));
-	options.add(make_opt( out_filename, "out", 'o', "output file", CCmdOptionFlags::required_output, &imageio));
+	options.add(make_opt( out_filename, "out-image", 'o', "output file", CCmdOptionFlags::required_output, &imageio));
 	
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
diff --git a/src/3dimagefilter.cc b/src/3dimagefilter.cc
index cf0a827..5ae446f 100644
--- a/src/3dimagefilter.cc
+++ b/src/3dimagefilter.cc
@@ -57,8 +57,6 @@ int do_main( int argc, char *argv[] )
 			      CCmdOptionFlags::required_input, &imageio));
 	options.add(make_opt( out_filename, "out-file", 'o', "output image(s) that have been filtered", 
 			      CCmdOptionFlags::required_output, &imageio));
-	options.add(make_help_opt( "help-plugins", 0, "give some help about the filter plugins", 
-				   new TPluginHandlerHelpCallback<C3DFilterPluginHandler>)); 
 
 	if (options.parse(argc, argv, "filter", &filter_plugins) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
diff --git a/src/3dimagefilterstack.cc b/src/3dimagefilterstack.cc
index 79959a5..e8aa3d8 100644
--- a/src/3dimagefilterstack.cc
+++ b/src/3dimagefilterstack.cc
@@ -72,13 +72,9 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt( in_filename, "in-file", 'i', "input image(s) to be filtered", CCmdOptionFlags::required_input, &imageio));
 	options.add(make_opt( out_filename, "out-file", 'o', "output file name base, numbers are added accorfing to the input "
 			      "file pattern, and the file  extension is added according to the 'type' option.", 
-			      CCmdOptionFlags::required, &imageio));
+			      CCmdOptionFlags::required_output, &imageio));
 	options.add(make_opt( out_type, imageio.get_set(), "type", 't',"output file type", CCmdOptionFlags::required));
 	
-	options.add(make_help_opt( "help-plugins", 0,
-				   "give some help about the filter plugins", 
-				   new TPluginHandlerHelpCallback<C3DFilterPluginHandler>)); 
-
 	if (options.parse(argc, argv, "filter", &filter_plugins) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 
diff --git a/src/3dimagestats.cc b/src/3dimagestats.cc
index 868a09b..e509580 100644
--- a/src/3dimagestats.cc
+++ b/src/3dimagestats.cc
@@ -87,7 +87,8 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt( in_filename, "in-file", 'i', "input image(s) to be filtered", 
 			      CCmdOptionFlags::required_input, &imageio));
 	options.add(make_opt( thresh, "thresh", 't', "intensity thresh to ignore"));
-
+	options.set_stdout_is_result();
+	
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 
diff --git a/src/3dlandmarks-distances.cc b/src/3dlandmarks-distances.cc
index bba662c..ec192ee 100644
--- a/src/3dlandmarks-distances.cc
+++ b/src/3dlandmarks-distances.cc
@@ -57,7 +57,7 @@ int do_main(int argc, char **argv)
 
 	options.add(make_opt( src1_filename, "in-file-1", 'i', "input landmark set 1", CCmdOptionFlags::required_input, &lmxio));
 	options.add(make_opt( src2_filename, "in-file-2", 'o', "input landmark set 2", CCmdOptionFlags::required_input, &lmxio));
-
+	options.set_stdout_is_result();
 
         if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
diff --git a/src/3dlerp.cc b/src/3dlerp.cc
index 96bb6ee..7c5e128 100644
--- a/src/3dlerp.cc
+++ b/src/3dlerp.cc
@@ -19,6 +19,9 @@
  */
 
 #include <climits>
+
+#define BOOST_TEST_MAIN
+#define BOOST_TEST_NO_MAIN
 #include <boost/test/unit_test_suite.hpp>
 #include <boost/test/unit_test.hpp>
 #include <boost/test/floating_point_comparison.hpp>
@@ -38,8 +41,10 @@ const SProgramDescription g_description = {
         {pdi_group, "Analysis, filtering, combining, and segmentation of 3D images"}, 
 	{pdi_short, "Linearly combine two 3D images."}, 
 	{pdi_description, "merge two images by linear combination."}, 
-	{pdi_example_descr, "Combine image inputA.v and inputB.v by using position "
-	 "coordinates 4, 7, and 9 and write the result to output.v"}, 
+	{pdi_example_descr, "Combine image inputA.v and inputB.v by using position coordinates "
+	 "4, 7, and 9. This means the output pixel values will be evaluated according to\n\n"
+	 "    (9-7)/(9-4) * A + (7-4)/(9-4) * B  \n\n"
+	 "The result image will be written to output.v"}, 
 	{pdi_example_code, "-1 inputA.v -2 inputB.v -p 4,7,9 -o output.v"}
 }; 
 
@@ -87,7 +92,7 @@ private:
 	float m_w;
 };
 
-static void run_self_test()
+BOOST_AUTO_TEST_CASE( run_self_test )
 {
 	const C3DBounds size(1,2,1);
 
@@ -113,11 +118,7 @@ static void run_self_test()
 
 }
 
-static bool init_unit_test_suite( )
-{
-	::boost::unit_test::framework::master_test_suite().add( BOOST_TEST_CASE( &run_self_test));
-	return true;
-}
+SELFTEST_CALLBACK(CSelftest);
 
 template <typename F>
 struct FFilter {
@@ -141,7 +142,7 @@ int do_main(int argc, char **argv)
 	string src1_filename;
 	string src2_filename;
 	string out_filename;
-	bool self_test = false;
+	int self_test_result = 0;
 
 	vector<float> positions;
 
@@ -153,13 +154,17 @@ int do_main(int argc, char **argv)
 			      CCmdOptionFlags::required_output, &imageio));
 	options.add(make_opt( positions, "positions", 'p', 
 				    "image series positions (first, target, second)", CCmdOptionFlags::required));
-	options.add(make_opt( self_test, "self-test", 0, "run a self test of the tool"));
+	
+	options.add_selftest(self_test_result, new CSelftest(argc, argv));
 
-	if (options.parse(argc, (const char **)argv) != CCmdOptionList::hr_no)
-		return EXIT_SUCCESS; 
 
-	if (self_test) {
-		return ::boost::unit_test::unit_test_main( &init_unit_test_suite, argc, argv );
+	switch (options.parse(argc, argv, "boost-test-options")) {
+	case CCmdOptionList::hr_no:
+		break; 
+	case CCmdOptionList::hr_selftest: 
+		return self_test_result; 
+	default: 
+		return EXIT_SUCCESS; 
 	}
 
 	if (positions.size() != 3) {
diff --git a/src/3dnonrigidreg.cc b/src/3dnonrigidreg.cc
index c4d2df5..dd43467 100644
--- a/src/3dnonrigidreg.cc
+++ b/src/3dnonrigidreg.cc
@@ -59,13 +59,13 @@ int do_main( int argc, char *argv[] )
 
 	CCmdOptionList options(g_description);
 	options.set_group("IO"); 
-	options.add(make_opt( src_filename, "in", 'i', "test image", 
+	options.add(make_opt( src_filename, "in-image", 'i', "test image", 
 			      CCmdOptionFlags::required_input, &image3dio));
-	options.add(make_opt( ref_filename, "ref", 'r', "reference image", 
+	options.add(make_opt( ref_filename, "ref-image", 'r', "reference image", 
 			      CCmdOptionFlags::required_input, &image3dio));
-	options.add(make_opt( out_filename, "out", 'o', "registered output image", 
+	options.add(make_opt( out_filename, "out-image", 'o', "registered output image", 
 			      CCmdOptionFlags::required_output, &image3dio));
-	options.add(make_opt( trans_filename, "trans", 't', "output transformation", 
+	options.add(make_opt( trans_filename, "transformation", 't', "output transformation", 
 			      CCmdOptionFlags::output, &transform3dio));
 	
 	options.set_group("Registration"); 
diff --git a/src/3drigidreg.cc b/src/3drigidreg.cc
index ef8e272..8a9ca13 100644
--- a/src/3drigidreg.cc
+++ b/src/3drigidreg.cc
@@ -63,13 +63,13 @@ int do_main( int argc, char *argv[] )
 
 	CCmdOptionList options(g_description);
 	options.set_group("File I/O"); 
-	options.add(make_opt( src_filename, "in", 'i', "test image", 
+	options.add(make_opt( src_filename, "in-image", 'i', "test image", 
 			      CCmdOptionFlags::required_input, &C3DImageIOPluginHandler::instance()));
-	options.add(make_opt( ref_filename, "ref", 'r', "reference image", 
+	options.add(make_opt( ref_filename, "ref-image", 'r', "reference image", 
 			      CCmdOptionFlags::required_input, &C3DImageIOPluginHandler::instance()));
-	options.add(make_opt( out_filename, "out", 'o', "registered output image", 
+	options.add(make_opt( out_filename, "out-image", 'o', "registered output image", 
 			      CCmdOptionFlags::required_output, &C3DImageIOPluginHandler::instance()));
-	options.add(make_opt( trans_filename, "trans", 't', "transformation output file name", 
+	options.add(make_opt( trans_filename, "transformation", 't', "transformation output file name", 
 			      CCmdOptionFlags::output, &C3DTransformationIOPluginHandler::instance() ));
 
 	
diff --git a/src/3dseries-track-intensity.cc b/src/3dseries-track-intensity.cc
index 4776bed..481fa44 100644
--- a/src/3dseries-track-intensity.cc
+++ b/src/3dseries-track-intensity.cc
@@ -106,7 +106,7 @@ int do_main( int argc, char *argv[] )
 	options.add(make_opt( in_filename, "in-file", 'i', 
 			      "input perfusion data set", CCmdOptionFlags::required_input, &C3DImageIOPluginHandler::instance()));
 	options.add(make_opt( out_filename, "out-file", 'o', 
-			      "file name for output intensity slopes")); 
+			      "file name for output intensity slopes", CCmdOptionFlags::required_output)); 
 	
 	
 	if (options.parse(argc, argv, "points") != CCmdOptionList::hr_no)
diff --git a/src/3dvfcompare.cc b/src/3dvfcompare.cc
index 4ce93a0..2ac9a05 100644
--- a/src/3dvfcompare.cc
+++ b/src/3dvfcompare.cc
@@ -22,7 +22,7 @@
 #include <mia/core/cmdlineparser.hh>
 #include <mia/3d/vfio.hh>
 #include <mia/internal/main.hh>
-
+#include <iostream>
 
 NS_MIA_USE
 using namespace std;
@@ -48,7 +48,8 @@ int do_main(int argc, char **argv)
 	options.add(make_opt( vf1_filename, "in-file-1", '1', "input vector field 1", CCmdOptionFlags::required_input, &vfio));
 	options.add(make_opt( vf2_filename, "in-file-2", '2', "input vector field 2", CCmdOptionFlags::required_input, &vfio));
 	options.add(make_opt( delta, "delta", 'd', "Maximum difference between vector to be ignored"));
-
+	options.set_stdout_is_result();
+	
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
 	
@@ -79,6 +80,7 @@ int do_main(int argc, char **argv)
 		++ivf1; 
 		++ivf2; 
 	}
+	std::cout  << (diff ? "0" : "1") << "\n"; 
 	return diff ? EXIT_FAILURE : EXIT_SUCCESS;	
 }
 
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 056743e..b36b275 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -17,9 +17,12 @@
 #
 #
 
-ADD_CUSTOM_TARGET(manpages)
+ADD_CUSTOM_TARGET(xmldoc)
 
-ADD_CUSTOM_TARGET(XMLDOC)
+INCLUDE (${CMAKE_SOURCE_DIR}/doc/MiaDoctools.cmake)
+
+SET(NIPYPE_INTERFACE_INIT_FILE ${CMAKE_CURRENT_BINARY_DIR}/__init__.py)
+MIA_PREPARE_AUTODOC(mia)
 
 ADD_CUSTOM_TARGET(mandir COMMAND mkdir -p ${CMAKE_BINARY_DIR}/doc/man)
 
@@ -55,7 +58,8 @@ DEFEXE(2dfuzzysegment     mia2d )
 DEFEXE(2dsegment-ahmed    mia2d )
 DEFEXE(2dsegment-fuzzyw   mia2d )
 DEFEXE(2dmultiimagevar    mia2d )
-#DEFEXE(2dmulti-force      mia2d )
+DEFEXE(2dmultiimageregistration    mia2d )
+DEFEXE(2dmulti-force      mia2d )
 DEFEXE(2dimagefullstats   mia2d )
 DEFEXE(2dbinarycombine    mia2d )
 DEFEXE(2dtransformation-to-strain mia2d)
@@ -66,7 +70,7 @@ DEFCHKEXE(2dlerp mia2d )
 
 #Programs related to 2D myocardic perfusion 
 
-DEFCHKEXE(2dsegshift          mia2dmyocardperf )
+DEFEXE(2dsegshift             mia2dmyocardperf )
 DEFEXE(2dsegshiftperslice     mia2dmyocardperf )
 DEFEXE(2dsegseriesstats       mia2dmyocardperf )
 DEFEXE(2dseries2dordermedian  mia2dmyocardperf )
@@ -92,6 +96,7 @@ DEFEXE(2dmyocard-segment      mia2dmyocardperf )
 DEFEXE(2dmyopgt-nonrigid      mia2dmyocardperf )
 DEFEXE(2dmany2one-nonrigid    mia2dmyocardperf )
 DEFEXE(2dmyoset-all2one-nonrigid    mia2dmyocardperf )
+
 IF(ITPP_FOUND) 
   DEFEXE(2dmyoica-full      mia2dmyocardperf )
   DEFEXE(2dmyoicapgt        mia2dmyocardperf )
@@ -177,10 +182,3 @@ ADD_SUBDIRECTORY(fluid2d  )
 ADD_SUBDIRECTORY(fluid3d  )
 ADD_SUBDIRECTORY(isosurface  )
 
-ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_BINARY_DIR}/doc/program.xml 
-  COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_SOURCE_DIR}/doc/miaxml2sgml.py ${CMAKE_SOURCE_DIR}/doc ${CMAKE_BINARY_DIR}/doc
-  DEPENDS XMLDOC
-  )
-    
-ADD_CUSTOM_TARGET(process_xml DEPENDS ${CMAKE_BINARY_DIR}/doc/program.xml)
-
diff --git a/src/__init__.py b/src/__init__.py
new file mode 100644
index 0000000..88da350
--- /dev/null
+++ b/src/__init__.py
@@ -0,0 +1 @@
+# init file for the nipype module 
diff --git a/src/filenumberpattern.cc b/src/filenumberpattern.cc
index 8bd5501..3f41e00 100644
--- a/src/filenumberpattern.cc
+++ b/src/filenumberpattern.cc
@@ -49,6 +49,7 @@ int do_main( int argc, char *argv[] )
 	CCmdOptionList options(g_description);
 	options.add(make_opt( in_filename, "in-file", 'i', "input image example name", 
 			      CCmdOptionFlags::required_input));
+	options.set_stdout_is_result(); 
 
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
diff --git a/src/fluid2d/CMakeLists.txt b/src/fluid2d/CMakeLists.txt
index 25d2213..e482e4f 100644
--- a/src/fluid2d/CMakeLists.txt
+++ b/src/fluid2d/CMakeLists.txt
@@ -20,6 +20,7 @@ SET(fluid2d_SOURCES main.cc vfluid.cc elast.cc helpers.cc)
 
 ADD_EXECUTABLE(mia-2dfluid ${fluid2d_SOURCES})
 TARGET_LINK_LIBRARIES(mia-2dfluid mia2d)
-CREATE_EXE_DOCU(2dfluid)
+MIA_EXE_CREATE_DOCU_AND_INTERFACE(mia 2dfluid)
+
 INSTALL(TARGETS mia-2dfluid RUNTIME DESTINATION "bin")
 
diff --git a/src/fluid2d/main.cc b/src/fluid2d/main.cc
index 98f9c63..05d0001 100644
--- a/src/fluid2d/main.cc
+++ b/src/fluid2d/main.cc
@@ -110,13 +110,13 @@ int do_main(int argc, char *argv[])
 	CCmdOptionList options(g_description);
 	
 	options.set_group("File-IO"); 
-	options.add(make_opt( src_filename, "in-image", 'i', "input (model) image to be registered", 
+	options.add(make_opt( src_filename, "in-image", 'i', "input (test) image to be registered", 
 			      CCmdOptionFlags::required_input, &imageio));
 	options.add(make_opt( ref_filename, "ref-image", 'r', "reference image", 
 			      CCmdOptionFlags::required_input, &imageio));
-	options.add(make_opt( out_filename, "out", 'o', "output vector field", 
+	options.add(make_opt( out_filename, "out-transformation", 'o', "output transformation comprising the registration", 
 			      CCmdOptionFlags::output, &C2DVFIOPluginHandler::instance()));
-	options.add(make_opt( def_filename, "deformed-image", 'd', "deformed registered image", 
+	options.add(make_opt( def_filename, "out-image", 'd', "output image deformed according to the transformation", 
 			      CCmdOptionFlags::output, &imageio));
 
 	options.set_group("Registration parameters"); 
diff --git a/src/fluid3d/CMakeLists.txt b/src/fluid3d/CMakeLists.txt
index 05858b7..4a1eb46 100644
--- a/src/fluid3d/CMakeLists.txt
+++ b/src/fluid3d/CMakeLists.txt
@@ -26,9 +26,10 @@ ADD_DEFINITIONS(-DVSTREAM_DOMAIN=\"fluid3d\")
 
 ADD_EXECUTABLE(mia-3dfluid ${fluid3d_SOURCES})
 TARGET_LINK_LIBRARIES(mia-3dfluid mia3d)
-CREATE_EXE_DOCU(3dfluid)
 INSTALL(TARGETS mia-3dfluid RUNTIME DESTINATION "bin")
 
+MIA_EXE_CREATE_DOCU_AND_INTERFACE(mia 3dfluid)
+
 
 
 
diff --git a/src/fluid3d/main.cc b/src/fluid3d/main.cc
index fcd587e..bb853d2 100644
--- a/src/fluid3d/main.cc
+++ b/src/fluid3d/main.cc
@@ -122,12 +122,11 @@ int do_main(int argc, char *argv[])
 	options.set_group("File-IO"); 
 	options.add(make_opt( in_filename, "in-image", 'i', "input image", CCmdOptionFlags::required_input, &imageio ));
 	options.add(make_opt( ref_filename, "ref-image", 'r', "reference image ", CCmdOptionFlags::required_input, &imageio ));
-	options.add(make_opt( out_filename, "out-deformation", 'o', "output vector field", 
+	options.add(make_opt( out_filename, "out-transformation", 'o', "output transformation comprising the registering transformation field",
 			      CCmdOptionFlags::required_output, &C3DTransformationIOPluginHandler::instance()));
 
-	options.add(make_opt(deformed_filename, "deformed-image", 'd', "save deformed image", 
-			     CCmdOptionFlags::output, &imageio)); 
-
+	options.add(make_opt( deformed_filename, "out-image", 'd', "save deformed image", 
+			      CCmdOptionFlags::output, &imageio)); 
 
 	options.set_group("Registration parameters"); 
 	options.add(make_opt( disable_multigrid, "disable-multigrid", 0, "disable multi-grid processing"));
@@ -166,7 +165,6 @@ int do_main(int argc, char *argv[])
 	P3DFVectorfield result = fluid_transform(params,solver,!disable_multigrid,
 						 !disable_fullres,&g_MeasureList, ipf);
 
-
 	auto vftranscreator  = produce_3dtransform_factory("vf:imgkernel=[bspline:d=1],imgboundary=zero");
 	
 	auto transform = vftranscreator->create(result->get_size()); 
diff --git a/src/isosurface/CMakeLists.txt b/src/isosurface/CMakeLists.txt
index 0b93b38..6818aa2 100644
--- a/src/isosurface/CMakeLists.txt
+++ b/src/isosurface/CMakeLists.txt
@@ -38,12 +38,12 @@ IF(GTS_FOUND)
 
   # add the ISO-surface programs 
   ADD_EXECUTABLE(mia-3disosurface-from-volume iso.cc)
-  CREATE_EXE_DOCU(3disosurface-from-volume)
+  MIA_EXE_CREATE_DOCU_AND_INTERFACE(mia 3disosurface-from-volume)
   TARGET_LINK_LIBRARIES(mia-3disosurface-from-volume miagts)
   INSTALL(TARGETS mia-3disosurface-from-volume RUNTIME DESTINATION "bin")
 
   ADD_EXECUTABLE(mia-3disosurface-from-stack iso_from_slices.cc)
-  CREATE_EXE_DOCU(3disosurface-from-stack)
+  MIA_EXE_CREATE_DOCU_AND_INTERFACE(mia 3disosurface-from-stack)
   TARGET_LINK_LIBRARIES(mia-3disosurface-from-stack miagts)
   INSTALL(TARGETS mia-3disosurface-from-stack RUNTIME DESTINATION "bin")
 
diff --git a/src/meshfilter.cc b/src/meshfilter.cc
index 0dfb532..4aaa6fa 100644
--- a/src/meshfilter.cc
+++ b/src/meshfilter.cc
@@ -51,10 +51,6 @@ int do_main( int argc, char *argv[] )
 	CCmdOptionList options(g_general_help);
 	options.add(make_opt( in_filename, "in-file", 'i', "input mesh to be filtered", CCmdOptionFlags::required_input, &meshio));
 	options.add(make_opt( out_filename, "out-file", 'o', "output mesh that have been filtered", CCmdOptionFlags::required_output, &meshio));
-	options.set_group(g_help_optiongroup); 
-	options.add(make_help_opt( "help-filters", 0,
-				   "give some help about the filter plugins", 
-				   new TPluginHandlerHelpCallback<CMeshFilterPluginHandler>));
 	
 	if (options.parse(argc, argv, "filter", &filter_plugins) != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
diff --git a/src/multihist.cc b/src/multihist.cc
index 32b406c..3c5f34a 100644
--- a/src/multihist.cc
+++ b/src/multihist.cc
@@ -115,7 +115,7 @@ int do_main( int argc, char *argv[] )
 	CCmdOptionList options(g_description);
 	options.add(make_opt( in_filename, "in-file", 'i', "input image(s) to be filtered", 
 			      CCmdOptionFlags::required_input, &imageio));
-	options.add(make_opt( out_filename, "out", 'o', "output file name", 
+	options.add(make_opt( out_filename, "out-histogram", 'o', "output file name", 
 			      CCmdOptionFlags::required_output));
 	options.add(make_opt( hmin, "min", 0, "minimum of histogram range"));
 	options.add(make_opt( hmax, "max", 0, "maximum of histogram range"));
diff --git a/src/myowavelettest.cc b/src/myowavelettest.cc
index d31dbce..5cb8a1d 100644
--- a/src/myowavelettest.cc
+++ b/src/myowavelettest.cc
@@ -67,7 +67,8 @@ int do_main( int argc, char *argv[] )
 	options.set_group("File-IO"); 
 	options.add(make_opt( in_filename, "in-file", 'i', "input data set", 
 			      CCmdOptionFlags::required_input));
-
+	options.set_stdout_is_result();
+	
 	if (options.parse(argc, argv) != CCmdOptionList::hr_no) 
 		return EXIT_SUCCESS; 
 	
diff --git a/src/plugin-help.cc b/src/plugin-help.cc
index 70d28da..9cc3a07 100644
--- a/src/plugin-help.cc
+++ b/src/plugin-help.cc
@@ -99,8 +99,10 @@ map<string, const CPluginHandlerBase*> collect_handlers()
 int do_main( int argc, char *argv[] )
 {
 	CCmdOptionList options(description);
+	options.set_stdout_is_result();
 	if (options.parse(argc, argv, "plugin-descriptor") != CCmdOptionList::hr_no)
 		return EXIT_SUCCESS; 
+
 		
 	auto handlers = collect_handlers(); 
 		
diff --git a/src/test_plugins_as_installed.cc b/src/test_plugins_as_installed.cc
index af1275e..c022c0b 100644
--- a/src/test_plugins_as_installed.cc
+++ b/src/test_plugins_as_installed.cc
@@ -74,6 +74,7 @@ BOOST_FIXTURE_TEST_CASE(test_C3DImageIOPluginHandler,PluginTestFixture)
 		"inria", 
 		"hdf5", 
 		"mhd", 
+		"nifti", 
 		"vff", 
 		"vti", 
 		"vtk", 
@@ -103,7 +104,8 @@ BOOST_FIXTURE_TEST_CASE(test_C3DImageCreatorPluginHandler,PluginTestFixture)
 BOOST_FIXTURE_TEST_CASE(test_C3DTransformCreatorHandler,PluginTestFixture) 
 {
 	set<string> test_data = { 
-		"affine", "axisrot", "raffine", "rigid", "spline", "translate", "rotation", "vf"
+		"affine", "axisrot", "raffine", "rigid", "spline", 
+		"translate", "rotation", "rotbend", "vf"
 	}; 
 	test(C3DTransformCreatorHandler::instance().get_set(), test_data); 
 }
@@ -217,7 +219,7 @@ BOOST_FIXTURE_TEST_CASE(test_C2DVFIOPluginHandler,PluginTestFixture)
 BOOST_FIXTURE_TEST_CASE(test_C2DFullCostPluginHandler,PluginTestFixture) 
 {
 	set<string> test_data = {
-		"image", "maskedimage"
+		"image", "labelimage", "maskedimage"
 	}; 
 	
 	test(C2DFullCostPluginHandler::instance().get_set(), test_data); 
@@ -260,7 +262,7 @@ BOOST_FIXTURE_TEST_CASE(test_C2DFilterPluginHandler,PluginTestFixture)
 		"adaptmed", "admean", "aniso", "bandpass", "binarize", "combiner",
 		"convert", "close", "crop", "dilate", "distance", 
 		"downscale", "erode", "gauss", "gradnorm", "invert", "kmeans", 
-		"label", "labelmap", "load", "mask", "mean", "median", "mlv", 
+		"label", "labelmap", "labelscale", "load", "mask", "mean", "median", "mlv", 
 		"ngfnorm", "noise", "open", "pruning", "regiongrow", "sandp", 
 		"scale", "selectbig", "sepconv", "shmean", "sort-label", "sws", 
 		"tee", "thinning", "thresh", "transform", "ws"

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/mia.git



More information about the debian-med-commit mailing list