changeset 2564:f99952fb216f

Merge remote branch 'origin/master'
author Andrew L Janke <a.janke@gmail.com>
date Wed, 22 Feb 2012 00:55:50 +1000
parents 4b26fb8b776c (current diff) 73b8c991cf38 (diff)
children 9a32f1651a9c
files Makefile.am progs/minccalc/y.tab.h
diffstat 58 files changed, 9345 insertions(+), 955 deletions(-) [+]
line wrap: on
line diff
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+*~
 INSTALL
 *.in
 *.o
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,8 +16,8 @@
 # Packaging defines
 SET(CPACK_GENERATOR TGZ)
 SET(CPACK_PACKAGE_VERSION_MAJOR 2)
-SET(CPACK_PACKAGE_VERSION_MINOR 0)
-SET(CPACK_PACKAGE_VERSION_PATCH 17)
+SET(CPACK_PACKAGE_VERSION_MINOR 1)
+SET(CPACK_PACKAGE_VERSION_PATCH 1)
 INCLUDE(CPack)
 
 
@@ -28,20 +28,20 @@
 SET(PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
 SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
 
+OPTION(BUILD_MINC2      "Support minc2 file format" ON)
+OPTION(BUILD_TOOLS      "Build minc tools (mincreshape,mincresample, etc)" ON)
+OPTION(BUILD_CONVERTERS "Build minc conversion programs (mnc2nii, nii2mnc , dcm2mnc...)" ON)
+OPTION(BUILD_EZMINC     "Build C++ interface library EZminc" ON)
+IF(BUILD_EZMINC)
+OPTION(BUILD_MINC4ITK   "Build ITK interface" ON)
+ENDIF(BUILD_EZMINC)
 
-# yes, build as minc2
-SET(MINC2 "1")
+
 ADD_DEFINITIONS(-DHAVE_CONFIG_H)
 
 # aliases
 SET(VERSION "${PACKAGE_VERSION}")
 
-# progs needed to build
-#SET(FLEX_FIND_REQUIRED)
-#SET(BISON_FIND_REQUIRED)
-#FIND_PACKAGE(BISON)
-#FIND_PACKAGE(FLEX)
-
 # check for prereqs
 INCLUDE(CheckFunctionExists)
 
@@ -52,11 +52,15 @@
 CHECK_INCLUDE_FILES(float.h HAVE_FLOAT_H)
 
 # netcdf and HDF5
-SET(NETCDF_FIND_REQUIRED TRUE)
-SET(HDF5_FIND_REQUIRED TRUE)
-FIND_PACKAGE(HDF5)
-FIND_PACKAGE(NETCDF)
-INCLUDE_DIRECTORIES( ${NETCDF_INCLUDE_DIR} ${HDF5_INCLUDE_DIR} )
+FIND_PACKAGE(NETCDF REQUIRED)
+INCLUDE_DIRECTORIES( ${NETCDF_INCLUDE_DIR} )
+
+IF(BUILD_MINC2)
+  FIND_PACKAGE(HDF5 REQUIRED)
+  FIND_PACKAGE(ZLIB REQUIRED)
+  SET(MINC2 "1")
+  INCLUDE_DIRECTORIES( ${HDF5_INCLUDE_DIR} )
+ENDIF(BUILD_MINC2)
 
 # config files for build
 CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/config.h.cmake ${CMAKE_SOURCE_DIR}/config.h)
@@ -68,10 +72,16 @@
 INCLUDE_DIRECTORIES(
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_SOURCE_DIR}/libsrc
-   ${CMAKE_SOURCE_DIR}/libsrc2
    ${CMAKE_SOURCE_DIR}/volume_io/Include
    )
 
+IF(BUILD_MINC2)
+  INCLUDE_DIRECTORIES(
+   ${CMAKE_SOURCE_DIR}/libsrc2
+   )
+ENDIF(BUILD_MINC2)
+
+
 # some variables
 SET(minc1_LIB_SRCS
    libsrc/ParseArgv.c
@@ -105,26 +115,56 @@
    libsrc2/volume.c
    )
 
+SET(minc_LIB minc)
+
+IF(BUILD_MINC2)
+  SET(minc_LIB_SRCS ${minc1_LIB_SRCS} ${minc2_LIB_SRCS})
+  SET(minc_LIB minc2)
+  ADD_LIBRARY(minc2 STATIC ${minc_LIB_SRCS} )
+
+  TARGET_LINK_LIBRARIES(minc2 ${NETCDF_LIBRARY} ${HDF5_LIBRARY} ${ZLIB_LIBRARIES} m )
+
+  INSTALL(TARGETS minc2 ARCHIVE DESTINATION lib)
+
+  INSTALL(FILES libsrc/minc.h libsrc/ParseArgv.h 
+    libsrc/voxel_loop.h 
+    libsrc/nd_loop.h
+    libsrc/time_stamp.h
+    libsrc/minc_compat.h
+    volume_io/Include/volume_io.h
+    libsrc2/minc2.h
+    libsrc/minc_simple.h
+    DESTINATION include
+    )
+
+  SET_TARGET_PROPERTIES(minc2 PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
+
+ELSE(BUILD_MINC2)
+
+    SET(minc_LIB_SRCS ${minc1_LIB_SRCS} )
+    SET(minc_LIB minc)
+    ADD_LIBRARY(minc STATIC ${minc1_LIB_SRCS} )
+    TARGET_LINK_LIBRARIES(minc ${NETCDF_LIBRARY} )
+    INSTALL(TARGETS minc ARCHIVE DESTINATION lib)
+
+    INSTALL(FILES libsrc/minc.h libsrc/ParseArgv.h 
+      libsrc/voxel_loop.h 
+      libsrc/nd_loop.h
+      libsrc/time_stamp.h
+      libsrc/minc_compat.h
+      volume_io/Include/volume_io.h
+      libsrc/minc_simple.h
+      DESTINATION include
+      )
+
+    SET_TARGET_PROPERTIES(minc PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
+
+ENDIF(BUILD_MINC2)
 
 # build the main minc2 library
-ADD_LIBRARY(minc2 STATIC ${minc1_LIB_SRCS} ${minc2_LIB_SRCS})
-INSTALL(TARGETS minc2 DESTINATION lib)
-INSTALL(FILES libsrc/minc.h libsrc/ParseArgv.h 
-   libsrc/voxel_loop.h 
-   libsrc/nd_loop.h
-   libsrc/time_stamp.h
-   libsrc/minc_compat.h
-   volume_io/Include/volume_io.h
-   libsrc2/minc2.h
-   libsrc/minc_simple.h
-   DESTINATION include
-   )
-
-SET_TARGET_PROPERTIES(minc2 PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
-
 
 # volume_io2
-SET(volume_io2_LIB_SRCS
+SET(volume_io_LIB_SRCS
    volume_io/Geometry/colour.c
    volume_io/Geometry/colour_def.c
    volume_io/Geometry/gaussian.c
@@ -161,9 +201,20 @@
    volume_io/Volumes/volumes.c
    )
 
-# build and install volume_io2 library
-ADD_LIBRARY(volume_io2 STATIC ${volume_io2_LIB_SRCS})
-INSTALL(TARGETS volume_io2 DESTINATION lib)
+IF(BUILD_MINC2)
+  # build and install volume_io2 library
+  ADD_LIBRARY(volume_io2 STATIC ${volume_io_LIB_SRCS})
+  INSTALL(TARGETS volume_io2 ARCHIVE DESTINATION lib)
+  SET_TARGET_PROPERTIES(volume_io2 PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
+  SET( volume_io_LIB volume_io2)
+
+ELSE(BUILD_MINC2)
+  ADD_LIBRARY(volume_io STATIC ${volume_io_LIB_SRCS})
+  INSTALL(TARGETS volume_io ARCHIVE DESTINATION lib)
+  SET_TARGET_PROPERTIES(volume_io PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
+  SET( volume_io_LIB volume_io)
+ENDIF(BUILD_MINC2)
+
 INSTALL(FILES volume_io/Include/volume_io/alloc.h
 	volume_io/Include/volume_io/arrays.h 
 	volume_io/Include/volume_io/basic.h 
@@ -182,13 +233,20 @@
 	volume_io/Include/volume_io/volume_cache.h
    DESTINATION include/volume_io)
 
-SET_TARGET_PROPERTIES(volume_io2 PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
-
-
+IF(BUILD_TOOLS)
 # now build the progs subdir
 ADD_SUBDIRECTORY( progs )
+ENDIF(BUILD_TOOLS)
 
-
+IF(BUILD_CONVERTERS)
 # and then the conversion subdir
 ADD_SUBDIRECTORY( conversion )
+ENDIF(BUILD_CONVERTERS)
 
+IF(BUILD_EZMINC)
+ADD_SUBDIRECTORY( ezminc )
+ENDIF(BUILD_EZMINC)
+
+IF(BUILD_MINC4ITK AND BUILD_EZMINC)
+ADD_SUBDIRECTORY( minc4itk )
+ENDIF(BUILD_MINC4ITK AND BUILD_EZMINC)
\ No newline at end of file
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2011-12-20  Andrew L Janke <a.janke@gmail.com>
+   * libsrc/netcdf_convenience.c: changed execute_decompress_command()
+      to always decompress the whole file as the approach used for
+      netCDF files for header_only does not work with HDF5 MINC2 files
+   * merged Vlad's ezminc branch
+
+2011-06-29  Andrew L Janke  <a.janke@gmail.com>
+   * configure.in: changed typo from enable to disable minc2
+
+2011-05-30  Andrew L Janke  <a.janke@gmail.com>
+   * progs/minccalc: added imax() and imin() operators
 
 2011-04-29  Andrew L Janke  <a.janke@gmail.com>
    * libsrc2/volume.c: added minc_version global
--- a/Makefile.am
+++ b/Makefile.am
@@ -82,7 +82,7 @@
 	progs/Proglib/minc_def.h \
 	progs/minccalc/errx.h \
 	progs/minccalc/node.h \
-	progs/minccalc/y.tab.h \
+	progs/minccalc/gram.h \
 	progs/mincresample/mincresample.h \
 	progs/mincreshape/mincreshape.h \
 	libsrc2/minc2_private.h \
--- a/configure.in
+++ b/configure.in
@@ -16,7 +16,6 @@
 AM_PROG_CC_C_O
 AC_PROG_F77
 AM_PROG_LEX
-AM_PROG_LEX
 AC_PROG_YACC
 
 AC_HEADER_TIME
@@ -42,7 +41,7 @@
 mni_REQUIRE_LIB(m,[#include <math.h>],[double x = sqrt(3.);])
 mni_REQUIRE_LIB(netcdf,[#include <netcdf.h>],[int i = ncopen("",0);])
 AC_ARG_ENABLE(disminc2,
-    [  --disable-minc2          enable HDF5 (MINC 2) functionality],
+    [  --disable-minc2         disable HDF5 (MINC 2) functionality],
     [ case "${disableval}" in
       yes) disminc2=true ;;
       no)  disminc2=false ;;
--- a/conversion/CMakeLists.txt
+++ b/conversion/CMakeLists.txt
@@ -2,8 +2,13 @@
 #
 # Andrew Janke - a.janke@gmail.com
 
-LINK_DIRECTORIES(../)
-LINK_LIBRARIES( minc2 ${NETCDF_LIBRARY} ${HDF5_LIBRARY} )
+#LINK_DIRECTORIES()
+IF(BUILD_MINC2)
+  LINK_LIBRARIES( minc2 ${NETCDF_LIBRARY} ${HDF5_LIBRARY} )
+ELSE(BUILD_MINC2)
+  LINK_LIBRARIES( minc ${NETCDF_LIBRARY} )
+ENDIF(BUILD_MINC2)
+
 ADD_DEFINITIONS(-DHAVE_CONFIG_H)
 
 
@@ -19,9 +24,8 @@
    Acr_nema/group.c
    Acr_nema/message.c
    Acr_nema/value_repr.c)
-#INSTALL(TARGETS acr_nema DESTINATION lib)
 
-ADD_EXECUTABLE(../dcm2mnc
+ADD_EXECUTABLE(dcm2mnc
    dcm2mnc/dcm2mnc.c
    dcm2mnc/dicom_to_minc.c
    dcm2mnc/siemens_to_dicom.c
@@ -29,49 +33,60 @@
    dcm2mnc/minc_file.c
    dcm2mnc/progress.c
    dcm2mnc/string_to_filename.c)
-TARGET_LINK_LIBRARIES(../dcm2mnc acr_nema )
+TARGET_LINK_LIBRARIES(dcm2mnc acr_nema )
 
-ADD_EXECUTABLE(../ecattominc
+ADD_EXECUTABLE(ecattominc
    ecattominc/ecattominc.c
    ecattominc/insertblood.c
    ecattominc/ecat_file.c
    ecattominc/machine_indep.c
    )
-ADD_EXECUTABLE(../minctoecat
+ADD_EXECUTABLE(minctoecat
    minctoecat/minctoecat.c
    minctoecat/ecat_write.c
    minctoecat/machine_indep.c
    )
-TARGET_LINK_LIBRARIES(../minctoecat volume_io2 minc2)
 
-ADD_EXECUTABLE(../mnc2nii
+IF(BUILD_MINC2)
+  TARGET_LINK_LIBRARIES(minctoecat volume_io2 minc2)
+ELSE(BUILD_MINC2)
+  TARGET_LINK_LIBRARIES(minctoecat volume_io minc)
+ENDIF(BUILD_MINC2)
+
+
+ADD_EXECUTABLE(mnc2nii
    nifti1/mnc2nii.c
    nifti1/nifti1_io.c
    nifti1/znzlib.c
    )
-ADD_EXECUTABLE(../nii2mnc
+ADD_EXECUTABLE(nii2mnc
    nifti1/nii2mnc.c
    nifti1/nifti1_io.c
    nifti1/znzlib.c
    )
-TARGET_LINK_LIBRARIES(../nii2mnc volume_io2 minc2)
 
-ADD_EXECUTABLE(../upet2mnc
+IF(BUILD_MINC2)
+  TARGET_LINK_LIBRARIES(nii2mnc volume_io2 minc2)
+ELSE(BUILD_MINC2)
+  TARGET_LINK_LIBRARIES(nii2mnc volume_io minc)
+ENDIF(BUILD_MINC2)
+
+ADD_EXECUTABLE(upet2mnc
    micropet/upet2mnc.c
    )
 
-ADD_EXECUTABLE(../vff2mnc
+ADD_EXECUTABLE(vff2mnc
    vff2mnc/vff2mnc.c
    )
 
 
 # install progs
 INSTALL(TARGETS
-   ../dcm2mnc
-   ../ecattominc
-   ../minctoecat
-   ../mnc2nii
-   ../nii2mnc
-   ../upet2mnc
-   ../vff2mnc
+   dcm2mnc
+   ecattominc
+   minctoecat
+   mnc2nii
+   nii2mnc
+   upet2mnc
+   vff2mnc
    DESTINATION bin)
--- a/conversion/minctoecat/machine_indep.c
+++ b/conversion/minctoecat/machine_indep.c
@@ -61,7 +61,7 @@
 }
 
 #if defined(__alpha) || defined(_WIN32) /* LITTLE_ENDIAN : alpha, intel */
-ftovaxf(f, bufr)
+void ftovaxf(f, bufr)
 float f;
 unsigned short *bufr;
 {
@@ -84,7 +84,7 @@
 	bufr[1] =  ret >>16;
 }
 #else  /* BIG ENDIAN : sun hp sgi*/
-ftovaxf(orig,number)
+void ftovaxf(orig,number)
   unsigned short number[2];
   float orig;
 {
new file mode 100644
--- /dev/null
+++ b/ezminc/CMakeLists.txt
@@ -0,0 +1,35 @@
+OPTION(BUILD_EZMINC_EXAMPLES   "Build EZminc examples" ON)
+
+
+
+IF(BUILD_MINC2)
+  ADD_DEFINITIONS( -DMINC2 )
+ENDIF(BUILD_MINC2)
+
+
+SET( MINC_IO_HEADERS 
+    minc_io_exceptions.h 
+    minc_io_fixed_vector.h  
+    minc_io_simple_volume.h
+    minc_1_rw.h
+    minc_1_simple.h
+    minc_1_simple_rw.h
+    minc_io_4d_volume.h
+   )
+   
+SET( MINC_IO_SRC 
+    minc_1_rw.cpp
+    minc_1_simple_rw.cpp
+  )
+
+
+ADD_LIBRARY( minc_io ${MINC_IO_HEADERS} ${MINC_IO_SRC})
+TARGET_LINK_LIBRARIES(minc_io ${minc_LIB})
+
+INSTALL(TARGETS minc_io ARCHIVE DESTINATION lib)
+INSTALL(FILES  ${MINC_IO_HEADERS} DESTINATION include)
+
+
+IF(BUILD_EZMINC_EXAMPLES)
+ADD_SUBDIRECTORY(examples)
+ENDIF(BUILD_EZMINC_EXAMPLES)
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/ezminc/examples/CMakeLists.txt
@@ -0,0 +1,13 @@
+LINK_LIBRARIES( minc_io )
+
+ADD_EXECUTABLE(fuzzy_volume_similarity fuzzy_volume_similarity.cpp)
+ADD_EXECUTABLE(trilinear_resample trilinear_resample.cpp)
+ADD_EXECUTABLE(volume_avg volume_avg.cpp)
+ADD_EXECUTABLE(volume_msq_dist volume_msq_dist.cpp)
+ADD_EXECUTABLE(volume_similarity volume_similarity.cpp)
+
+INSTALL(TARGETS
+  fuzzy_volume_similarity
+  volume_similarity
+   DESTINATION bin)
+
new file mode 100644
--- /dev/null
+++ b/ezminc/examples/fuzzy_volume_similarity.cpp
@@ -0,0 +1,209 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       :  fuzzy_volume_similarity
+@DESCRIPTION:  an example of implimentation of fuzzy volume similarity 
+@COPYRIGHT  :
+              Copyright 2011 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include "minc_1_rw.h"
+#include <iostream>
+#include "minc_1_simple.h"
+#include <getopt.h>
+#include <algorithm>
+
+using namespace minc;
+
+void show_usage (const char * prog)
+{
+  std::cout<<"Program calculates fuzzy volume similarity metrics"<<std::endl
+          <<"based on :  William R. Crum, Oscar Camara, and Derek L. G. Hill"
+          <<"\"Generalized Overlap Measures for Evaluation and Validation in Medical Image Analysis \""
+          <<" IEEE TRANSACTIONS ON MEDICAL IMAGING, VOL. 25, NO. 11, NOVEMBER 2006"<<std::endl
+          <<"http://dx.doi.org/10.1109/TMI.2006.880587"<<std::endl<<std::endl
+          <<"Usage: "<<prog<<" <input1.mnc> <input2.mnc> [--verbose --mask <mask.mnc>]"<<std::endl;
+  
+}
+
+template<class T>class find_min_max
+{
+  public:
+  T _min;
+  T _max;
+  bool _initialized;
+  int _count;
+  
+  find_min_max():_initialized(false),_min(0),_max(0),_count(0)
+  {
+  }
+  
+  void operator()(const T& v)
+  {
+    if(_initialized)
+    {
+      if(v<_min) _min=v;
+      if(v>_max) _max=v;
+    } else {
+      _initialized=true;
+      _min=v;
+      _max=v;
+    }
+    _count++;
+  }
+  
+  const T& min(void) const {
+    return _min;
+  }
+  
+  const T& max(void) const{
+    return _max;
+  }
+  
+  int count(void) const {
+    return _count;
+  }
+};
+
+int main(int argc,char **argv)
+{
+  int verbose=0;
+  std::string mask_f;
+  static struct option long_options[] = {
+    {"verbose", no_argument,             &verbose, 1},
+    {"quiet",   no_argument,             &verbose, 0},
+    {"mask",     required_argument,              0,'m'},
+    
+    {0, 0, 0, 0}
+  };
+  
+  for (;;) {
+    /* getopt_long stores the option index here. */
+    int option_index = 0;
+
+    int c = getopt_long (argc, argv, "vqm:", long_options, &option_index);
+
+    /* Detect the end of the options. */
+    if (c == -1) break;
+
+    switch (c)
+    {
+      case 0:
+        break;
+      case 'v':
+        std::cout << "Version: 0.1" << std::endl;
+        return 0;
+      case 'm':
+        mask_f=optarg;
+        break;
+      case '?':
+        /* getopt_long already printed an error message. */
+      default:
+        show_usage (argv[0]);
+        return 1;
+    }
+  }
+
+  if((argc - optind) < 2) {
+    show_usage (argv[0]);
+    return 1;
+  }
+  
+  try
+  {
+    minc_1_reader rdr1;
+    rdr1.open(argv[optind]);
+    
+    minc_1_reader rdr2;
+    rdr2.open(argv[optind+1]);
+    
+    if(rdr1.dim_no()!=rdr2.dim_no() )
+    {
+      std::cerr<<"Different number of dimensions!"<<std::endl;
+      return 1;
+    }
+    unsigned long size=1;
+    
+    for(int i=0;i<5;i++)
+    {
+      if(rdr1.ndim(i)!=rdr2.ndim(i))
+        std::cerr<<"Different dimensions length! "<<std::endl;
+      
+      if(rdr1.ndim(i)>0) size*=rdr1.ndim(i);
+    }
+    
+    for(int i=0;i<5;i++)
+    {
+      if(rdr1.nspacing(i)!=rdr2.nspacing(i) )
+        std::cerr<<"Different step size! "<<std::endl;
+    }
+    
+    std::vector<unsigned char> mask(size,1);
+    if(!mask_f.empty())
+    {
+      minc_1_reader rdr_m;
+      rdr_m.open(mask_f.c_str());
+      
+      for(int i=0;i<5;i++)
+      {
+        if(rdr1.ndim(i)!=rdr_m.ndim(i))
+          std::cerr<<"Different mask dimensions length! "<<std::endl;
+        
+        if(rdr1.nspacing(i)!=rdr_m.nspacing(i) )
+          std::cerr<<"Different mask step size! "<<std::endl;
+      }
+      rdr_m.setup_read_byte();
+      load_standard_volume<unsigned char>(rdr_m,&mask[0]);
+    }
+    
+    rdr1.setup_read_double();
+    rdr2.setup_read_double();
+    
+    std::vector<double> buffer1(size),buffer2(size);
+    
+    load_standard_volume<double>(rdr1,&buffer1[0]);
+    load_standard_volume<double>(rdr2,&buffer2[0]);
+    
+    find_min_max<double> f1,f2;
+    
+    //get min and max
+    f1=std::for_each(buffer1.begin(), buffer1.end(), f1);
+    f2=std::for_each(buffer2.begin(), buffer2.end(), f2);
+    
+    if( verbose )
+    {
+      std::cout<<"Volume 1 min="<<(int)f1.min()<<" max="<<(int)f1.max()<<" count="<<f1.count()<<std::endl;
+      std::cout<<"Volume 2 min="<<(int)f2.min()<<" max="<<(int)f2.max()<<" count="<<f2.count()<<std::endl;
+    }
+
+    unsigned char low= std::min<double>(f1.min(), f2.min());
+    unsigned char hi = std::max<double>(f1.max(), f2.max());
+
+    int v1=0,v2=0;
+    double a=0.0,b=0.0,c=0.0,d=0.0;
+    for(int i=0; i<size ; i++ )
+    {
+      
+      if(mask[i]>0)
+      {
+        a+=std::min<double>(buffer1[i],buffer2[i]);
+        b+=std::max<double>(buffer1[i],buffer2[i]);
+      }
+    }
+
+    std::cout.precision(10);
+    std::cout<<a/b<<std::endl;
+
+    
+  } catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/ezminc/examples/trilinear_resample.cpp
@@ -0,0 +1,129 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       :  trilinear_resample
+@DESCRIPTION:  an example of using trilinear resampling algorithm
+@COPYRIGHT  :
+              Copyright 2011 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include "minc_1_rw.h"
+#include <iostream>
+#include "minc_1_simple.h"
+#include "minc_1_simple_rw.h"
+#include <getopt.h>
+#include <stdlib.h>
+#include <math.h>
+//based on http://www3.interscience.wiley.com/journal/121496529/abstract
+using namespace minc;
+
+void show_usage (const char * prog)
+{
+  std::cerr<<"Usage: "<<prog<<" <input.mnc> <output.mnc> [--step <f> --verbose ]"<<std::endl;
+}
+
+int main(int argc,char **argv)
+{
+  int verbose=0;
+  int csv=0;
+  int kappa=0,specificity=0,sensitivity=0;
+  int jaccard=0;
+  double _step=1.0;
+  static struct option long_options[] = {
+    {"verbose", no_argument,             &verbose, 1},
+    {"quiet",   no_argument,             &verbose, 0},
+    {"step",    required_argument,       0, 's'},
+    {0, 0, 0, 0}
+  };
+  
+  for (;;) {
+    /* getopt_long stores the option index here. */
+    int option_index = 0;
+
+    int c = getopt_long (argc, argv, "vq", long_options, &option_index);
+
+    /* Detect the end of the options. */
+    if (c == -1) break;
+
+    switch (c)
+    {
+      case 0:
+        break;
+      case 'v':
+        std::cout << "Version: 0.1" << std::endl;
+        return 0;
+      case 's':
+        _step=atof(optarg);
+        break;
+      case '?':
+        /* getopt_long already printed an error message. */
+      default:
+        show_usage (argv[0]);
+        return 1;
+    }
+  }
+
+  if((argc - optind) < 2) {
+    show_usage (argv[0]);
+    return 1;
+  }
+  
+  try
+  {
+    minc_1_reader rdr;
+    rdr.open(argv[optind],true);
+    minc::minc_info new_info;
+
+    //rdr.setup_read_float();
+    simple_volume<float> input_vol,output_vol;
+    load_simple_volume<float>(rdr,input_vol);
+    new_info=rdr.info();
+    
+    minc::fixed_vec<3,float> old_step;
+    minc::fixed_vec<3,float> old_start,new_start;
+    minc::fixed_vec<3,int> new_len;
+    
+    for(int i=1;i<4;i++)
+    {
+      old_step[i-1]=new_info[rdr.map_space(i)].step;
+      old_start[i-1]=new_info[rdr.map_space(i)].start;
+      
+      float len=(new_info[rdr.map_space(i)].length)*old_step[i-1];
+      
+      new_info[rdr.map_space(i)].start-=old_step[i-1];
+      new_info[rdr.map_space(i)].step=_step;
+      new_info[rdr.map_space(i)].start+=_step/2;
+      new_start[i-1]=new_info[rdr.map_space(i)].start;
+      
+      new_len[i-1]=new_info[rdr.map_space(i)].length=ceil(fabs(len/_step));
+    }
+    
+    output_vol.resize(new_len);
+    
+    for(int z=0;z<new_len[2];z++)
+      for(int y=0;y<new_len[1];y++)
+        for(int x=0;x<new_len[0];x++)
+        {
+          minc::fixed_vec<3,float> cc=IDX<float>(x*_step,y*_step,z*_step);
+          
+          cc+=new_start;
+          cc/=old_step;
+          cc-=old_start;
+          
+          output_vol.set(x,y,z,input_vol.interpolate(cc[0],cc[1],cc[2]));
+        }
+    minc_1_writer wrt;
+    wrt.open(argv[optind+1],new_info,2,NC_FLOAT);
+    save_simple_volume<float>(wrt,output_vol);
+  } catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/ezminc/examples/volume_avg.cpp
@@ -0,0 +1,148 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : volume_avg
+@DESCRIPTION: an example of calculating volume average
+@COPYRIGHT  :
+              Copyright 2009 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include "minc_1_rw.h"
+#include <iostream>
+#include "minc_1_simple.h"
+#include "minc_1_simple_rw.h"
+#include <getopt.h>
+#include <math.h>
+
+using namespace minc;
+
+void show_usage(const char *name)
+{
+  std::cerr 
+	  << "Usage: "<<name<<" <input1> .... <inputn>  <output> " << std::endl
+    << "\tn should be more than 1"<< std::endl
+    << "Optional parameters:" << std::endl
+    << "\t--verbose be verbose" << std::endl
+    << "\t--clobber clobber the output files" << std::endl
+    << "\t--sd <sd.mnc> "<< std::endl;
+}
+
+int main(int argc,char **argv)
+{
+  int clobber=0;
+  int verbose=0;
+  std::string sd_f;
+  
+	static struct option long_options[] =
+  {
+    {"verbose", no_argument, &verbose, 1},
+    {"quiet", no_argument, &verbose, 0},
+    {"clobber", no_argument, &clobber, 1},
+    {"sd", required_argument, 0, 's'},
+    {0, 0, 0, 0}
+  };
+  
+	int c;
+	for (;;)
+	{
+		/* getopt_long stores the option index here. */
+		int option_index = 0;
+
+		c = getopt_long (argc, argv, "s", long_options, &option_index);
+
+		/* Detect the end of the options. */
+		if (c == -1)
+			break;
+
+		switch (c)
+		{
+		case 0:
+			break;
+    case 's':
+      sd_f=optarg;
+      break;
+		case '?':
+			/* getopt_long already printed an error message. */
+		default:
+			show_usage(argv[0]);
+			return 1;
+		}
+	}
+
+	if ((argc - optind) < 3)
+	{
+		show_usage(argv[0]);
+		return 1;
+	}
+  
+  std::string output=argv[argc-1]; //last argument is output file... maybe we should make it a parameter instead?
+  argc-=optind;
+  
+  if(!clobber && !access (output.c_str(), F_OK))
+  {
+    std::cerr << output.c_str () << " Exists!" << std::endl;
+    return 1;
+  }
+
+	try
+  {
+    
+    minc_1_reader rdr1;
+    rdr1.open(argv[optind]);
+    minc_float_volume _avg;
+    
+    load_simple_volume<float>(rdr1,_avg);
+    
+    minc_float_volume _sd(_avg);
+    minc_float_volume _tmp(_avg);
+    
+
+    for(int i=0;i<_avg.c_buf_size();i++)
+    {
+      _sd.c_buf()[i]=_avg.c_buf()[i]*_avg.c_buf()[i];
+    }
+    
+    for(int i=1;i<(argc-1);i++)
+    {
+      minc_1_reader rdr2;
+      rdr2.open(argv[optind+i]);
+      if(!is_same(rdr1,rdr2))
+      {
+        return 1;
+      }
+      
+      load_simple_volume<float>(rdr2,_tmp);
+      _avg+=_tmp;
+      _tmp*=_tmp;
+      _sd+=_tmp;
+    }
+    _avg/=(float)(argc-1);
+    for(int i=0;i<_avg.c_buf_size();i++)
+    {
+      _sd.c_buf()[i]=sqrt(_sd.c_buf()[i]/(argc-1) - _avg.c_buf()[i]*_avg.c_buf()[i] );
+    }
+    minc_1_writer wrt;
+    wrt.open(output.c_str(),rdr1.info(),2,NC_FLOAT);
+    save_simple_volume<float>(wrt,_avg);
+    
+    if(!sd_f.empty())
+    {
+      minc_1_writer wrt2;
+      wrt2.open(sd_f.c_str(),rdr1.info(),2,NC_FLOAT);
+      save_simple_volume<float>(wrt2,_sd);
+    }
+    
+	} catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  
+  return 0;
+}
+
new file mode 100644
--- /dev/null
+++ b/ezminc/examples/volume_msq_dist.cpp
@@ -0,0 +1,98 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       :  volume_msq_dist
+@DESCRIPTION:  an example of calculating mean squared dissimilarity
+@COPYRIGHT  :
+              Copyright 2011 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include "minc_1_rw.h"
+#include <iostream>
+#include "minc_1_simple.h"
+
+using namespace minc;
+
+int main(int argc,char **argv)
+{
+  
+	try
+  {
+		if(argc<4) {
+      std::cerr<<"Usage: "<<argv[0]<<" <input1.mnc> <input2.mnc> <mask.mnc>"<<std::endl;
+      return 1;
+    }
+    minc_1_reader rdr1;
+    rdr1.open(argv[1]);
+    
+    minc_1_reader rdr2;
+    rdr2.open(argv[2]);
+    
+    minc_1_reader rdr_m;
+    rdr_m.open(argv[3]);
+   
+    if(rdr1.dim_no()!=rdr2.dim_no() || rdr1.dim_no()!=rdr_m.dim_no())
+    {
+      std::cerr<<"Different number of dimensions!"<<std::endl;
+      return 1;
+    }
+    unsigned long size=1;
+    for(int i=0;i<5;i++)
+    {
+      if(rdr1.ndim(i)!=rdr2.ndim(i) || rdr1.ndim(i)!=rdr_m.ndim(i))
+      {
+        std::cerr<<"Different dimensions length! "<<std::endl;
+      }
+      if(rdr1.ndim(i)>0) size*=rdr1.ndim(i);
+    }
+    
+    for(int i=0;i<5;i++)
+    {
+      if(rdr1.nspacing(i)!=rdr2.nspacing(i) ||  rdr1.nspacing(i)!=rdr_m.nspacing(i))
+      {
+        std::cerr<<"Different step size! "<<std::endl;
+      }
+    }
+    
+    //std::cout<<size<<std::endl;
+    rdr1.setup_read_float();
+    rdr2.setup_read_float();
+    rdr_m.setup_read_byte();
+    
+    std::vector<float> buffer1(size),buffer2(size);
+    std::vector<unsigned char> mask(size);
+    
+    load_standard_volume<float>(rdr1,&buffer1[0]);
+    load_standard_volume<float>(rdr2,&buffer2[0]);
+    load_standard_volume<unsigned char>(rdr_m,&mask[0]);
+    
+    double avg=0;
+    int cnt=0;
+    for(int i=0;i<size;i++)
+    {
+      if(!mask[i]) continue;
+      double d=buffer1[i]-buffer2[i];
+      avg+=d*d;
+      cnt++;
+    }
+    if(cnt)
+      avg/=cnt;
+    if( rdr1.ndim(0)==3 )  //this is a grid file
+      avg*=3;
+    std::cout.precision(10);
+    std::cout<<avg<<std::endl;
+    
+	} catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  
+  return 0;
+}
+
new file mode 100644
--- /dev/null
+++ b/ezminc/examples/volume_similarity.cpp
@@ -0,0 +1,259 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       :  volume_similarity
+@DESCRIPTION:  an example of calculating volume similarity metrics 
+@COPYRIGHT  :
+              Copyright 2011 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include "minc_1_rw.h"
+#include <iostream>
+#include "minc_1_simple.h"
+#include <getopt.h>
+#include <algorithm>
+
+using namespace minc;
+
+void show_usage (const char * prog)
+{
+  std::cout<<"Program calculates volume similarity metrics"<<std::endl
+           <<"if multiple labels are present, similarity metrics will be calculated for each label separately"<<std::endl
+          <<"based on : M. Feuerman and A. R. Miller "
+          <<"\"Relationships between statistical measures of agreement: sensitivity, specificity and kappa\""
+          <<" Journal of Evaluation in Clinical Practice vol. 14 no. 5 pp 930-933 2008"<<std::endl
+          <<"http://dx.doi.org/10.1111/j.1365-2753.2008.00984.x"<<std::endl<<std::endl
+          <<"Usage: "<<prog<<" <input1.mnc> <input2.mnc> [--kappa --sensitivity --specificity --verbose --jaccard --csv]"<<std::endl;
+  
+}
+
+template<class T>class find_min_max
+{
+  public:
+  T _min;
+  T _max;
+  bool _initialized;
+  int _count;
+  
+  find_min_max():_initialized(false),_min(0),_max(0),_count(0)
+  {
+  }
+  
+  void operator()(const T& v)
+  {
+    if(_initialized)
+    {
+      if(v<_min) _min=v;
+      if(v>_max) _max=v;
+    } else {
+      _initialized=true;
+      _min=v;
+      _max=v;
+    }
+    _count++;
+  }
+  
+  const T& min(void) const {
+    return _min;
+  }
+  
+  const T& max(void) const{
+    return _max;
+  }
+  
+  int count(void) const {
+    return _count;
+  }
+};
+
+int main(int argc,char **argv)
+{
+  int verbose=0;
+  int csv=0;
+  int kappa=0,specificity=0,sensitivity=0;
+  int jaccard=0;
+  static struct option long_options[] = {
+    {"verbose", no_argument,             &verbose, 1},
+    {"quiet",   no_argument,             &verbose, 0},
+    {"kappa",   no_argument,             &kappa, 1},
+    {"sensitivity",   no_argument,       &sensitivity, 1},
+    {"specificity",   no_argument,       &specificity, 1},
+    {"jaccard",       no_argument,       &jaccard, 1},
+    {"csv",           no_argument,       &csv, 1},
+    {0, 0, 0, 0}
+  };
+  
+  for (;;) {
+    /* getopt_long stores the option index here. */
+    int option_index = 0;
+
+    int c = getopt_long (argc, argv, "vq", long_options, &option_index);
+
+    /* Detect the end of the options. */
+    if (c == -1) break;
+
+    switch (c)
+    {
+      case 0:
+        break;
+      case 'v':
+        std::cout << "Version: 0.1" << std::endl;
+        return 0;
+      case '?':
+        /* getopt_long already printed an error message. */
+      default:
+        show_usage (argv[0]);
+        return 1;
+    }
+  }
+
+  if((argc - optind) < 2) {
+    show_usage (argv[0]);
+    return 1;
+  }
+  
+  if(! (sensitivity||specificity||kappa||jaccard) ) //no options selected, do all 
+  {
+    verbose=1;
+    sensitivity=1;
+    specificity=1;
+    kappa=1;
+    jaccard=1;
+  }
+  
+  try
+  {
+    minc_1_reader rdr1;
+    rdr1.open(argv[optind]);
+    
+    minc_1_reader rdr2;
+    rdr2.open(argv[optind+1]);
+    
+    if(rdr1.dim_no()!=rdr2.dim_no() )
+    {
+      std::cerr<<"Different number of dimensions!"<<std::endl;
+      return 1;
+    }
+    unsigned long size=1;
+    
+    for(int i=0;i<5;i++)
+    {
+      if(rdr1.ndim(i)!=rdr2.ndim(i))
+        std::cerr<<"Different dimensions length! "<<std::endl;
+      
+      if(rdr1.ndim(i)>0) size*=rdr1.ndim(i);
+    }
+    
+    for(int i=0;i<5;i++)
+    {
+      if(rdr1.nspacing(i)!=rdr2.nspacing(i) )
+        std::cerr<<"Different step size! "<<std::endl;
+    }
+    
+    rdr1.setup_read_byte();
+    rdr2.setup_read_byte();
+    
+    std::vector<unsigned char> buffer1(size),buffer2(size);
+    
+    load_standard_volume<unsigned char>(rdr1,&buffer1[0]);
+    load_standard_volume<unsigned char>(rdr2,&buffer2[0]);
+    
+    find_min_max<unsigned char> f1,f2;
+    
+    //get min and max
+    f1=std::for_each(buffer1.begin(), buffer1.end(), f1);
+    f2=std::for_each(buffer2.begin(), buffer2.end(), f2);
+    
+    if( verbose && !csv)
+    {
+      //std::cout<<buffer1.size() << std::endl;
+      //std::cout<<buffer1.begin()<<" "<<buffer1.end()<<std::endl;
+
+      std::cout<<"Volume 1 min="<<(int)f1.min()<<" max="<<(int)f1.max()<<" count="<<f1.count()<<std::endl;
+      std::cout<<"Volume 2 min="<<(int)f2.min()<<" max="<<(int)f2.max()<<" count="<<f2.count()<<std::endl;
+    }
+
+    unsigned char low= std::min<unsigned char>(f1.min(), f2.min());
+    unsigned char hi = std::max<unsigned char>(f1.max(), f2.max());
+
+    if(low==0) low=1; //assume 0 is background
+
+
+    for(unsigned char label=low; label<=hi; label++)
+    {
+      int v1=0,v2=0;
+      double a=0.0,b=0.0,c=0.0,d=0.0;
+      for(int i=0; i<size ; i++ )
+      {
+        if( buffer1[i]==label ) v1++;
+        if( buffer2[i]==label ) v2++;
+        if( buffer1[i]==label && buffer2[i]==label ) a++;
+        if( buffer1[i]==label && buffer2[i]!=label ) c++;
+        if( buffer1[i]!=label && buffer2[i]==label ) b++;
+        if( buffer1[i]!=label && buffer2[i]!=label ) d++;
+      }
+      double _kappa=0.0;
+      double _sensitivity=0.0;
+      double _specificity=0.0;
+      double _jaccard=0.0;
+
+      if(v1>0 && v2>0)
+      {
+        //_kappa=v1v2*2.0/(v1+v2);
+        _kappa=a*2.0/(v1+v2);
+
+        _sensitivity=a/(a+c);
+        _specificity=d/(b+d);
+
+        _jaccard=a/(a+c+b);
+      }
+
+      std::cout.precision(10);
+
+      if( hi!=low && verbose && !csv)
+        std::cout<<"Label: "<<(int)label<<std::endl;
+
+      if( csv )
+      {
+        if(low!=hi)
+          std::cout<<(int)label<<",";
+
+        std::cout<<_kappa<<",";
+        std::cout<<_sensitivity<<",";
+        std::cout<<_specificity<<",";
+        std::cout<<_jaccard<<std::endl;
+      } else {
+        if( kappa ){
+          if(verbose) std::cout<<"Kappa ";
+          std::cout<<_kappa<<std::endl;
+        }
+        if( sensitivity )
+        {
+          if(verbose) std::cout<<"Sensitivity ";
+          std::cout<<_sensitivity<<std::endl;
+        }
+        if( specificity )
+        {
+          if(verbose) std::cout<<"Specificity ";
+          std::cout<<_specificity<<std::endl;
+        }
+        if( jaccard )
+        {
+          if(verbose) std::cout<<"Jaccard similarity ";
+          std::cout<<_jaccard<<std::endl;
+        }
+      }
+    }
+    
+  } catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/ezminc/minc_1_rw.cpp
@@ -0,0 +1,1421 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : 
+@DESCRIPTION: Primitive" interface to minc files, using minctoraw and rawtominc programs
+              does not require linking with minc2 library.
+              Created during the days when minc2 didn't compile on 64bit architecture
+@COPYRIGHT  :
+              Copyright 2007 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include <stdio.h>
+#include <iostream>
+#include <sstream>
+#include <string.h>
+//minc stuff
+#include <math.h>
+#include <limits.h>
+#include "minc_1_rw.h"
+
+namespace minc
+{
+  dim_info::dim_info(int l, double sta,
+                     double spa,dimensions d,
+                     bool hd):
+      length(l),start(sta),step(spa),dim(d),have_dir_cos(hd)
+  {
+    switch(dim)
+    {
+      case dim_info::DIM_X:name=MIxspace;break;
+      case dim_info::DIM_Y:name=MIyspace;break;
+      case dim_info::DIM_Z:name=MIzspace;break;
+      case dim_info::DIM_TIME:name=MItime;break;
+      case dim_info::DIM_VEC:name=MIvector_dimension;break;
+      default: REPORT_ERROR("Unknown Dimension!");
+    }
+  }
+  
+  minc_1_base::minc_1_base():
+    _dims(3,0),
+    _map_to_std(5,-1),
+    _mincid(MI_ERROR),
+    _imgid(MI_ERROR),
+    _icvid(MI_ERROR),
+    _cur(MAX_VAR_DIMS,0),
+    _slab(MAX_VAR_DIMS,1),
+    _last(false),
+    _datatype(MI_ORIGINAL_TYPE),
+    _io_datatype(MI_ORIGINAL_TYPE),
+    _slab_len(0),
+    _positive_directions(true),
+    _minc2(false)
+  {
+    _icvid=miicv_create();
+  }
+
+  //! destructor, closes minc file
+  minc_1_base::~minc_1_base()
+  {
+    close();
+  }
+  
+  void minc_1_base::close(void)
+  {
+    if(_icvid!=MI_ERROR)
+    {
+      miicv_free(_icvid);
+      _icvid=MI_ERROR;
+    }
+    if(_mincid!=MI_ERROR) miclose(_mincid);
+    _mincid=MI_ERROR;
+  }
+  
+  
+  std::string minc_1_base::history(void) const
+  {
+    nc_type datatype;
+    int att_length;
+#ifndef WIN32
+    int op=ncopts;
+#endif //WIN32
+    //ncopts=0;
+    if ((ncattinq(_mincid, NC_GLOBAL, MIhistory, &datatype,&att_length) == MI_ERROR) ||
+        (datatype != NC_CHAR))
+    {
+      //ncopts=op;
+      return "";
+    }
+    char* str = new char[att_length+1];
+    str[0] = '\0';
+    miattgetstr(_mincid, NC_GLOBAL, (char*)MIhistory, att_length,str);
+    //ncopts=op;
+    std::string r(str);
+    delete [] str;
+    return r;
+  }
+  
+  //code from mincinfo
+  int minc_1_base::var_number(void) const
+  {
+    int nvars;
+    if(ncinquire(_mincid, NULL, &nvars, NULL, NULL)!=MI_ERROR)
+      return nvars;
+    return 0;
+  }
+  
+  std::string minc_1_base::var_name(int no) const
+  {
+    char name[MAX_NC_NAME];
+    if(ncvarinq(_mincid, no, name, NULL, NULL, NULL, NULL)!=MI_ERROR)
+      return name;
+  }
+  
+  int minc_1_base::att_number(const char *var_name) const
+  {
+    int varid;
+    int natts;
+    if (*var_name=='\0') {
+        varid = NC_GLOBAL;
+    } else {
+      if((varid = ncvarid(_mincid, var_name))==MI_ERROR)
+        return 0;
+    }
+    return att_number(varid);
+  }
+  
+  int minc_1_base::var_id(const char *var_name) const
+  {
+    return ncvarid(_mincid, var_name);
+  }
+
+  long minc_1_base::var_length(const char *var_name) const
+  {
+    int varid=var_id(var_name);
+    if(varid!=MI_ERROR)
+      return var_length(varid);
+    else
+      return 0;
+  }
+    
+  long minc_1_base::var_length(int var_id) const
+  {
+    int vardims;
+    
+    if(ncvarinq(_mincid, var_id, NULL, NULL, &vardims, NULL, NULL)!=MI_ERROR)
+    {
+      if(vardims==0) return 1;
+      int *dims=new int[vardims];
+      if(ncvarinq(_mincid, var_id, NULL, NULL, NULL, dims, NULL)!=MI_ERROR)
+      {
+        long varlength=1;
+        if(ncdiminq(_mincid,dims[0],NULL,&varlength)!=MI_ERROR)
+        {
+          delete[] dims;
+          return varlength;
+        }
+        delete[] dims;
+        return 1;
+      } else {
+        delete[] dims;
+        return 1;
+      }
+    }
+    return 0;
+  }
+
+  
+  //! get the number of attributes associated with variable
+  int minc_1_base::att_number(int var_no) const
+  {
+    int natts;
+    if(ncvarinq(_mincid, var_no, NULL, NULL, NULL, NULL, &natts)!=MI_ERROR)
+      return natts;
+    return 0;
+  }
+  
+  
+  std::string minc_1_base::att_name(const char *var_name,int no) const
+  {
+    int varid;
+    int attid;
+    char name[MAX_NC_NAME];
+    if (*var_name=='\0') 
+        varid = NC_GLOBAL;
+    else 
+    {
+      if((varid = ncvarid(_mincid, var_name))==MI_ERROR)
+        return "";
+    }
+    return att_name(varid,no);
+  }
+  
+  std::string minc_1_base::att_name(int varid,int no) const
+  {
+    int attid;
+    char name[MAX_NC_NAME];
+    if(ncattname(_mincid, varid, no, name)==MI_ERROR)
+      return "";
+    
+    return name;
+  }
+  
+  std::string minc_1_base::att_value_string(const char *var_name,const char *att_name) const
+  {
+    int varid;
+    int attid;
+    char name[MAX_NC_NAME];
+    if (*var_name=='\0') 
+        varid = NC_GLOBAL;
+    else 
+    {
+      if((varid = ncvarid(_mincid, var_name))==MI_ERROR)
+        return "";
+    }
+    return att_value_string(varid,att_name);
+  }
+  
+  std::string minc_1_base::att_value_string(int varid,const char *att_name) const
+  {
+    int att_length;
+    nc_type datatype;
+    
+    //TODO: make this handle other (double?) data types correctly
+    if ((ncattinq(_mincid, varid, (char *)att_name, &datatype,&att_length) == MI_ERROR) ||
+        (datatype != NC_CHAR))
+    {
+      //ncopts=op;
+      return "";
+    }
+    char* str = new char[att_length+1];
+    str[0] = '\0';
+    miattgetstr(_mincid, varid, (char *)att_name, att_length, str);
+    //ncopts=op;
+    std::string r(str);
+    delete [] str;
+    return r;
+  }
+  
+  std::vector<double> minc_1_base::att_value_double(const char *var_name,const char *att_name) const
+  {
+    int varid;
+    if (*var_name=='\0') 
+        varid = NC_GLOBAL;
+    else 
+    {
+      if((varid = ncvarid(_mincid, var_name))==MI_ERROR)
+        return std::vector<double>(0);
+    }
+    return att_value_double(varid,att_name);
+  }
+  
+  std::vector<short> minc_1_base::att_value_short(const char *var_name,const char *att_name) const
+  {
+    int varid;
+    if (*var_name=='\0') 
+      varid = NC_GLOBAL;
+    else 
+    {
+      if((varid = ncvarid(_mincid, var_name))==MI_ERROR)
+        return std::vector<short>(0);
+    }
+    return att_value_short(varid,att_name);
+  }
+  
+  std::vector<unsigned char> minc_1_base::att_value_byte(const char *var_name,const char *att_name) const
+  {
+    int varid;
+    if (*var_name=='\0') 
+      varid = NC_GLOBAL;
+    else 
+    {
+      if((varid = ncvarid(_mincid, var_name))==MI_ERROR)
+        return std::vector<unsigned char>(0);
+    }
+    return att_value_byte(varid,att_name);    
+  }
+  
+  
+  std::vector<int> minc_1_base::att_value_int(const char *var_name,const char *att_name) const
+  {
+    int varid;
+    if (*var_name=='\0') 
+      varid = NC_GLOBAL;
+    else 
+    {
+      if((varid = ncvarid(_mincid, var_name))==MI_ERROR)
+        return std::vector<int>(0);
+    }
+    return att_value_int(varid,att_name);
+  }
+  
+  std::vector<int> minc_1_base::att_value_int(int varid,const char *att_name) const 
+  {
+    int att_length;
+    nc_type datatype;
+    
+    if ((ncattinq(_mincid, varid, (char *)att_name, &datatype,&att_length) == MI_ERROR) ||
+         (datatype != NC_INT))
+    {
+      //ncopts=op;
+      return std::vector<int>(0);
+    }
+    std::vector<int> r(att_length);
+    miattget(_mincid, varid, (char*)att_name, NC_INT, att_length,&r[0], NULL) ;
+    //ncopts=op;
+    return r;
+  }
+
+  
+  std::vector<double> minc_1_base::att_value_double(int varid,const char *att_name) const
+  {
+    int att_length;
+    nc_type datatype;
+    
+    //TODO: make this handle other (double?) data types correctly
+    if ((ncattinq(_mincid, varid, (char *)att_name, &datatype,&att_length) == MI_ERROR) ||
+        (datatype != NC_DOUBLE))
+    {
+      //ncopts=op;
+      return std::vector<double>(0);
+    }
+    std::vector<double> r(att_length);
+    miattget(_mincid, varid, (char*)att_name, NC_DOUBLE, att_length,&r[0], NULL) ;
+    //ncopts=op;
+    return r;
+  }
+  
+  std::vector<short> minc_1_base::att_value_short(int varid,const char *att_name) const
+  {
+    int att_length;
+    nc_type datatype;
+    
+    //TODO: make this handle other (double?) data types correctly
+    if ((ncattinq(_mincid, varid, (char *)att_name, &datatype,&att_length) == MI_ERROR) ||
+         (datatype != NC_SHORT))
+    {
+      //ncopts=op;
+      return std::vector<short>(0);
+    }
+    std::vector<short> r(att_length);
+    miattget(_mincid, varid, (char*)att_name, NC_SHORT, att_length,&r[0], NULL) ;
+    //ncopts=op;
+    return r;
+  }
+  
+  std::vector<unsigned char> minc_1_base::att_value_byte(int varid,const char *att_name) const
+  {
+    int att_length;
+    nc_type datatype;
+    
+    //TODO: make this handle other (double?) data types correctly
+    if ((ncattinq(_mincid, varid, (char *)att_name, &datatype,&att_length) == MI_ERROR) ||
+         (datatype != NC_BYTE))
+    {
+      //ncopts=op;
+      return std::vector<unsigned char>(0);
+    }
+    std::vector<unsigned char> r(att_length);
+    miattget(_mincid, varid, (char*)att_name, NC_BYTE, att_length,&r[0], NULL) ;
+    //ncopts=op;
+    return r;
+  }
+  
+  
+  nc_type minc_1_base::att_type(const char *var_name,const char *att_name) const
+  {
+    int varid;
+    if (*var_name=='\0') 
+        varid = NC_GLOBAL;
+    else 
+    {
+      if((varid = ncvarid(_mincid, var_name))==MI_ERROR)
+        return MI_ORIGINAL_TYPE;
+    }
+    return att_type(varid,att_name);
+  }
+  
+  nc_type minc_1_base::att_type(int varid,const char *att_name) const
+  {
+    int att_length;
+    nc_type datatype;
+    
+    if(ncattinq(_mincid, varid, (char *)att_name, &datatype,&att_length) == MI_ERROR)
+      return MI_ORIGINAL_TYPE;
+    return datatype;
+  }
+  
+
+  int minc_1_base::att_length(const char *var_name,const char *att_name) const
+  {
+    int varid;
+    if (*var_name=='\0') 
+        varid = NC_GLOBAL;
+    else 
+    {
+      if((varid = ncvarid(_mincid, var_name))==MI_ERROR)
+        return 0;
+    }
+    return att_length(varid,att_name);
+  }
+  
+  int minc_1_base::att_length(int varid,const char *att_name) const
+  {
+    int att_length;
+    nc_type datatype;
+    
+    if(ncattinq(_mincid, varid, (char *)att_name, &datatype,&att_length) == MI_ERROR)
+      return 0;
+    
+    return att_length;
+  }
+  
+  
+  minc_1_reader::minc_1_reader(const minc_1_reader&):_metadate_only(false),_have_temp_file(false),_read_prepared(false)
+  {
+  }
+  
+  minc_1_reader::minc_1_reader():_metadate_only(false),_have_temp_file(false),_read_prepared(false)
+  {
+  }
+  
+  
+  //based on the code from mincextract
+  void minc_1_reader::open(const char *path,bool positive_directions/*=true*/,bool metadate_only/*=false*/,bool rw/*=false*/)
+  {
+#ifndef WIN32
+    ncopts = 0;
+#endif 
+    _metadate_only=metadate_only;
+    _read_prepared=false;
+    int element_size;
+    int idim;
+    int nstart, ncount;
+    _positive_directions=positive_directions;
+    //ncopts = 0;
+
+    // Open the file 
+
+    // Expand file 
+    if(_metadate_only)
+    { 
+      int created_tempfile;
+      char * tempfile = miexpand_file((char*)path, NULL, true, &created_tempfile);
+      if (tempfile == NULL) REPORT_ERROR("Error expanding minc file");
+      _tempfile=tempfile;
+      path=_tempfile.c_str();
+      _have_temp_file=created_tempfile;
+    }
+    _mincid = miopen((char*)path, rw?NC_WRITE:NC_NOWRITE);
+
+    if(_mincid == MI_ERROR) REPORT_ERROR("Can't open minc file for reading!");
+#ifdef MINC2
+   if (MI2_ISH5OBJ(_mincid)) {
+     _minc2 = true;
+   }
+#endif
+
+    /* Inquire about the image variable */
+    _imgid = ncvarid(_mincid, MIimage);
+    if(_imgid == MI_ERROR) REPORT_ERROR("Can't get Image ID");
+    ncvarinq(_mincid, _imgid, NULL, NULL, &_ndims, mdims, NULL);
+    //get image data type... not used for now
+    miget_datatype(_mincid, _imgid, &_datatype, &_is_signed);
+    //dir_cos.SetIdentity();
+    int dim_cnt=0;
+    miget_image_range(_mincid, _image_range);
+    //go through dimensions , calculating parameters for reshaping into ZYX array if needed
+    _info.resize(_ndims);
+    _world_matrix.resize(_ndims*4,0.0);
+    _voxel_matrix.resize(_ndims*4,0);
+    //_dir_cos.resize(_ndims*_ndims,0.0);
+    
+    for(int i=_ndims-1;i>=0;i--) 
+    {
+      //_world_matrix[i*(_ndims+1)]=1.0;
+      //_voxel_matrix[i*(_ndims+1)]=1.0;
+      char dimname[MAX_NC_NAME];
+      long dimlength;
+      //get dimensions info
+      ncdiminq(_mincid, mdims[i], dimname, &dimlength);
+      _info[i].name=dimname;
+      _info[i].length=dimlength;
+      _info[i].have_dir_cos=false;
+      int axis=-1;
+      unsigned int sz=0;
+      
+      if(!strcmp(dimname,MIxspace))
+      { 
+        _dims[0]=dimlength;axis=0;
+        _info[i].dim=dim_info::DIM_X;
+        _map_to_std[1]=i;
+      } else if(!strcmp(dimname,MIyspace)) { 
+        _dims[1]=dimlength;axis=1;
+        _info[i].dim=dim_info::DIM_Y;
+        _map_to_std[2]=i;
+      } else if(!strcmp(dimname,MIzspace)) { 
+        _dims[2]=dimlength;axis=2;
+        _info[i].dim=dim_info::DIM_Z;
+        _map_to_std[3]=i;
+      } else if(!strcmp(dimname,MIvector_dimension)) { 
+         axis=-1;
+        _info[i].dim=dim_info::DIM_VEC;
+        _map_to_std[0]=i;
+      } else if(!strcmp(dimname,MItime)) { 
+         axis=3;
+        _info[i].dim=dim_info::DIM_TIME;
+        _map_to_std[4]=i;
+      } else  {
+        REPORT_ERROR ("Unknown dimension");
+        _info[i].dim=dim_info::DIM_UNKNOWN;
+      }
+      
+      if(_info[i].dim!=dim_info::DIM_VEC)
+      {
+        //ncopts = 0;
+        int dimid = ncvarid(_mincid, dimname);
+        //ncopts = NC_VERBOSE | NC_FATAL;
+        if (dimid == MI_ERROR) continue;
+               
+        // Get dimension attributes
+        //ncopts = 0;
+        miattget1(_mincid, dimid, (char*)MIstep, NC_DOUBLE, &_info[i].step);
+        if(_info[i].step == 0.0)
+           _info[i].step = 1.0;
+        miattget1(_mincid, dimid, (char*)MIstart, NC_DOUBLE, &_info[i].start);
+          
+        if(_positive_directions && _info[i].step<0.0)
+        {
+          _info[i].start+=_info[i].step*(dimlength-1);
+          _info[i].step=-_info[i].step;
+        }
+        
+        if(miattget(_mincid, dimid, (char*)MIdirection_cosines, NC_DOUBLE, 3, &_info[i].dir_cos[0], NULL)!= MI_ERROR)
+        {
+          _info[i].have_dir_cos=true;
+          
+          /* Normalize the direction cosine */
+          double len=sqrt(_info[i].dir_cos[0]*_info[i].dir_cos[0]+
+                          _info[i].dir_cos[1]*_info[i].dir_cos[1]+
+                          _info[i].dir_cos[2]*_info[i].dir_cos[2]);
+          
+          if(len>1e-6 && fabs(len-1.0)>1e-6) //TODO: use some epsiolon here?
+          {
+            for(int a=0;a<3;a++)
+              _info[i].dir_cos[a]/=len;
+          }
+          
+        } 
+        // fill voxel matrix
+        _voxel_matrix[i*4+axis]=1;
+      } else { //vectors don't have spatial component!
+        _info[i].start=0;
+        _info[i].step=0.0;
+        _info[i].dir_cos[0]=_info[i].dir_cos[1]=_info[i].dir_cos[2]=0.0;
+        _info[i].have_dir_cos=false;
+      }
+      
+      //fill world matrix
+      for(int a=0;a<3;a++)
+        _world_matrix[i*4+a]=_info[i].dir_cos[a]*_info[i].step;
+      if(axis==3) //time
+        _world_matrix[i*4+3]=_info[i].step;
+      else
+        _world_matrix[i*4+3]=0.0;
+    }
+    //ncopts = NC_VERBOSE | NC_FATAL;
+    
+    // now let's find out the slice dimensions
+    int idmax = ncvarid(_mincid, MIimagemax);
+    _slice_dimensions=0;
+    if(idmax != MI_ERROR) 
+    {
+      int nmax_dims;
+      int mmax_dims[MAX_VAR_DIMS];
+      ncvarinq(_mincid, _imgid, NULL, NULL, &nmax_dims, mmax_dims, NULL);
+      if(nmax_dims>0)
+        _slice_dimensions=_ndims-nmax_dims;
+    } 
+    
+    if(_slice_dimensions<=0)
+    {
+      if(_info[_ndims-1].dim==dim_info::DIM_VEC || _info[_ndims-1].dim==dim_info::DIM_TIME) 
+        _slice_dimensions=std::min(_ndims,3);
+      else 
+        _slice_dimensions=std::min(_ndims,2);
+    }
+    std::fill(_slab.begin(),_slab.end(),1);
+    _slab_len=1;
+    for(int i=0;i<_slice_dimensions;i++)
+    {
+      _slab[_ndims-i-1]=_info[_ndims-i-1].length;
+      _slab_len*=_info[_ndims-i-1].length;
+    }
+  }
+  
+  minc_1_reader::~minc_1_reader()
+  {
+    if(_have_temp_file)
+      remove(_tempfile.c_str());
+  }
+
+  minc_1_writer::minc_1_writer():
+      _set_image_range(false),_set_slice_range(false),
+      _calc_min_max(true),_write_prepared(false)
+  {
+  }
+
+  minc_1_writer::minc_1_writer(const minc_1_writer&):
+      _set_image_range(false),_set_slice_range(false),
+      _calc_min_max(true),_write_prepared(false)
+  {
+  }
+  
+  
+  void minc_1_writer::open(const char *path,const minc_info& inf,int slice_dimensions,nc_type datatype,int _s)
+  {
+#ifndef WIN32
+    ncopts = 0;
+#endif
+	  _info=inf;
+    //int  mdims[MAX_VAR_DIMS];
+    double vrange[2];
+    _write_prepared=false;
+    
+    _mincid = micreate((char*)path, NC_CLOBBER/*|MI2_CREATE_V2*/); //TODO: add environment variable checking
+#ifdef MINC2
+    if (MI2_ISH5OBJ(_mincid)) { //micreate might create MINC2 file if environment variable is set
+      _minc2 = true;
+    }
+#endif
+    _ndims=_info.size();
+    _datatype=datatype;
+    _slice_dimensions=slice_dimensions;
+    _is_signed=_s;
+    fill(_map_to_std.begin(),_map_to_std.end(),-1);
+    for(int i=_ndims-1;i>=0;i--)
+    {
+      //just a precaution
+      switch(_info[i].dim)
+      {
+        case dim_info::DIM_X:_info[i].name=MIxspace;_map_to_std[1]=i;break;
+        case dim_info::DIM_Y:_info[i].name=MIyspace;_map_to_std[2]=i;break;
+        case dim_info::DIM_Z:_info[i].name=MIzspace;_map_to_std[3]=i;break;
+        case dim_info::DIM_TIME:_info[i].name=MItime;_map_to_std[4]=i;break;
+        default:
+        case dim_info::DIM_VEC:_info[i].name=MIvector_dimension;_map_to_std[0]=i;break;
+        //default: REPORT_ERROR("Unknown Dimension!");
+      }
+      mdims[i]=ncdimdef(_mincid, _info[i].name.c_str(), _info[i].length);
+      if(_info[i].dim!=dim_info::DIM_VEC)
+      {
+        int dimid=micreate_std_variable(_mincid,(char*)_info[i].name.c_str(),NC_INT, 0, NULL);
+        miattputdbl(_mincid, dimid, (char*)MIstep,_info[i].step);
+        miattputdbl(_mincid, dimid, (char*)MIstart,_info[i].start);
+        
+        if(_info[i].have_dir_cos)
+          ncattput(_mincid, dimid, (char*)MIdirection_cosines,NC_DOUBLE, 3, _info[i].dir_cos);
+      }
+    }
+    _slab_len=1;
+    for(int i=0;i<_slice_dimensions;i++)
+    {
+      _slab[_ndims-i-1]=_info[_ndims-i-1].length;
+      _slab_len*=_info[_ndims-i-1].length;
+    }
+    
+    _icmax=_icmin=MI_ERROR;
+    //ncopts = NC_OPTS_VAL;
+    _imgid=micreate_std_variable(_mincid, (char*)MIimage, _datatype, _ndims, mdims);
+    _image_range[0]=DBL_MAX;_image_range[1]=-DBL_MAX;
+    
+    switch(_datatype)
+    {
+      case NC_DOUBLE:
+        vrange[0]=-DBL_MAX;vrange[1]=DBL_MAX;
+        _is_signed=1;
+        break;
+      case NC_FLOAT:
+        vrange[0]=-FLT_MAX;vrange[1]=FLT_MAX;
+        _is_signed=1;
+        break;
+      case NC_SHORT:
+        if(_is_signed)
+        {
+          vrange[0]=SHRT_MIN;
+          vrange[1]=SHRT_MAX;
+        } else {
+          vrange[0]=0;vrange[1]=USHRT_MAX;
+        }
+        break;
+      case NC_BYTE:
+        if(_is_signed)
+        {
+          vrange[0]=-128;vrange[1]=127;
+        } else {
+          vrange[0]=0;vrange[1]=255;
+        }
+        break;
+      case NC_INT:
+        if(_is_signed)
+        {
+          vrange[0]=INT_MIN;vrange[1]=INT_MAX;
+        }else{
+          vrange[0]=0;vrange[1]=UINT_MAX;
+        }
+        break;
+      default:break;
+    };
+    miattputstr(_mincid, _imgid, (char*)MIcomplete, (char*)MI_FALSE);
+    miattputstr(_mincid, _imgid, (char*)MIsigntype, (char*)(_is_signed?MI_SIGNED:MI_UNSIGNED));
+    ncattput(_mincid, _imgid, (char*)MIvalid_range, NC_DOUBLE, 2, vrange);
+    miset_valid_range(_mincid, _imgid, vrange);
+  }
+  
+  void minc_1_writer::open(const char *path,const minc_1_base& imitate)
+  {
+    
+    open(path,imitate.info(),imitate.slice_dimensions(), 
+         imitate.datatype(),imitate.is_signed());
+    
+    copy_headers(imitate);
+  }
+  
+  void minc_1_writer::open(const char *path,const char *imitate_file)
+  {
+    minc_1_reader rdr;
+    //open minc file in metadate mode
+    rdr.open(imitate_file,false,true);
+    open(path,rdr);
+    //copy_headers(rdr);
+  }
+   
+  void minc_1_writer::setup_write_float()
+  {
+    _image_range[0]=DBL_MAX;_image_range[1]=-DBL_MAX;
+    
+    switch(_datatype)
+    {
+      case NC_DOUBLE:
+        _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, 0, NULL);
+        _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, 0, NULL);
+      
+        _set_image_range=true;
+        _set_slice_range=false;
+        break;
+      
+      case NC_FLOAT:
+        _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, 0, NULL);
+        _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, 0, NULL);
+      
+        _set_image_range=true;
+        _set_slice_range=false;
+        break;
+      
+      case NC_SHORT:
+        
+          _set_image_range=false;
+          _set_slice_range=true;
+        
+          _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+          _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+        break;
+      
+      case NC_BYTE:
+        _set_image_range=false;
+        _set_slice_range=true;
+      
+        _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+        _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+        break;
+      case NC_INT:
+        _set_image_range=false;
+        _set_slice_range=true;
+      
+        _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+        _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+        break;
+      
+      default:
+        break;
+    };
+    ncendef(_mincid);
+    
+    if(_datatype==NC_DOUBLE || _datatype==NC_FLOAT)
+    {
+      miicv_setstr(_icvid, MI_ICV_SIGN,   (char*)MI_SIGNED);
+      miicv_setint(_icvid, MI_ICV_TYPE,    NC_FLOAT);
+      miicv_setint(_icvid, MI_ICV_DO_NORM,    true);
+      miicv_setint(_icvid, MI_ICV_USER_NORM, true);
+      miicv_setdbl(_icvid, MI_ICV_VALID_MIN, -FLT_MAX);
+      miicv_setdbl(_icvid, MI_ICV_VALID_MAX, FLT_MAX);
+      _calc_min_max=true;
+      
+    } else { //do something smart here?
+      miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_SIGNED);
+      miicv_setint(_icvid, MI_ICV_TYPE, NC_FLOAT);
+      miicv_setint(_icvid, MI_ICV_DO_NORM, false);
+      //miicv_setint(_icvid, MI_ICV_USER_NORM, false);
+      miicv_setdbl(_icvid, MI_ICV_VALID_MIN, -FLT_MAX);
+      miicv_setdbl(_icvid, MI_ICV_VALID_MAX, FLT_MAX);
+      _calc_min_max=true;
+      
+    }
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_FLOAT;
+    _write_prepared=true;
+  }
+  
+  void minc_1_writer::setup_write_double()
+  {
+    _image_range[0]=DBL_MAX;_image_range[1]=-DBL_MAX;
+    
+    switch(_datatype)
+    {
+      case NC_DOUBLE:
+        _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, 0, NULL);
+        _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, 0, NULL);
+      
+        _set_image_range=true;
+        _set_slice_range=false;
+        break;
+      
+      case NC_FLOAT:
+        _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, 0, NULL);
+        _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, 0, NULL);
+      
+        _set_image_range=true;
+        _set_slice_range=false;
+        break;
+      
+      case NC_SHORT:
+        
+          _set_image_range=false;
+          _set_slice_range=true;
+        
+          _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+          _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+        break;
+      
+      case NC_BYTE:
+        _set_image_range=false;
+        _set_slice_range=true;
+      
+        _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+        _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+        break;
+      case NC_INT:
+        _set_image_range=false;
+        _set_slice_range=true;
+      
+        _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+        _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, _ndims-_slice_dimensions, mdims);
+        break;
+      
+      default:
+        break;
+    };
+    ncendef(_mincid);
+    
+    if(_datatype==NC_DOUBLE)
+    {
+      miicv_setstr(_icvid, MI_ICV_SIGN,   (char*)MI_SIGNED);
+      miicv_setint(_icvid, MI_ICV_TYPE,    NC_DOUBLE);
+      miicv_setint(_icvid, MI_ICV_DO_NORM,    true);
+      miicv_setint(_icvid, MI_ICV_USER_NORM, true);
+      miicv_setdbl(_icvid, MI_ICV_VALID_MIN, -DBL_MAX);
+      miicv_setdbl(_icvid, MI_ICV_VALID_MAX, DBL_MAX);
+      _calc_min_max=true;
+      
+    } else if(_datatype==NC_FLOAT)  {
+      miicv_setstr(_icvid, MI_ICV_SIGN,   (char*)MI_SIGNED);
+      miicv_setint(_icvid, MI_ICV_TYPE,    NC_DOUBLE);
+      miicv_setint(_icvid, MI_ICV_DO_NORM,    true);
+      miicv_setint(_icvid, MI_ICV_USER_NORM, true);
+      miicv_setdbl(_icvid, MI_ICV_VALID_MIN, -DBL_MAX);
+      miicv_setdbl(_icvid, MI_ICV_VALID_MAX, DBL_MAX);
+      _calc_min_max=true;
+      
+    } else { //do something smart here?
+      miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_SIGNED);
+      miicv_setint(_icvid, MI_ICV_TYPE, NC_DOUBLE);
+      miicv_setint(_icvid, MI_ICV_DO_NORM, false);
+      //miicv_setint(_icvid, MI_ICV_USER_NORM, false);
+      miicv_setdbl(_icvid, MI_ICV_VALID_MIN, -DBL_MAX);
+      miicv_setdbl(_icvid, MI_ICV_VALID_MAX, DBL_MAX);
+      _calc_min_max=true;
+      
+    }
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_DOUBLE;
+    _write_prepared=true;
+  }
+  
+  void minc_1_writer::setup_write_short(bool n)
+  {
+    _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, 0, NULL);
+    _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, 0, NULL);
+    _set_image_range=true;
+    _set_slice_range=false;
+    
+    ncendef(_mincid);
+    
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_SHORT);
+    miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_SIGNED);
+    //miicv_setstr(_icvid, MI_ICV_SIGN, true);    
+    /* Set range of values */ //TODO: set this to something sensible?
+    miicv_setint(_icvid, MI_ICV_VALID_MIN, SHRT_MIN);
+    miicv_setint(_icvid, MI_ICV_VALID_MAX, SHRT_MAX);
+
+    /* No normalization so that pixels are scaled to the slice */
+    miicv_setint(_icvid, MI_ICV_DO_NORM, false);
+    miicv_setint(_icvid, MI_ICV_DO_RANGE, false);
+    
+    miicv_attach(_icvid, _mincid, _imgid);
+    
+    _io_datatype=NC_SHORT;
+    _write_prepared=true;
+  }
+  
+  void minc_1_writer::setup_write_ushort(bool n)
+  {
+    _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, 0, NULL);
+    _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, 0, NULL);
+    _set_image_range=true;
+    _set_slice_range=false;
+    
+    ncendef(_mincid);
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_SHORT);
+    miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_UNSIGNED);
+    miicv_setstr(_icvid, MI_ICV_SIGN, false); 
+    
+    /* Set range of values */ //TODO: set this to something sensible?
+    miicv_setint(_icvid, MI_ICV_VALID_MIN, 0);
+    miicv_setint(_icvid, MI_ICV_VALID_MAX, USHRT_MAX);
+
+    /* No normalization so that pixels are scaled to the slice */
+    miicv_setint(_icvid, MI_ICV_DO_NORM, false);
+    miicv_setint(_icvid, MI_ICV_DO_RANGE, false);
+    
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_SHORT;
+    _write_prepared=true;
+  }
+  
+  void minc_1_writer::setup_write_byte(bool n)
+  {
+    _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, 0, NULL);
+    _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, 0, NULL);
+    _set_image_range=true;
+    _set_slice_range=false;
+    
+    ncendef(_mincid);
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_BYTE);
+    miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_UNSIGNED);
+
+    /* Set range of values */ //TODO: set this to something sensible?
+    miicv_setint(_icvid, MI_ICV_VALID_MIN, 0);
+    miicv_setint(_icvid, MI_ICV_VALID_MAX, UCHAR_MAX);
+
+    /* No normalization so that pixels are scaled to the slice */
+    miicv_setint(_icvid, MI_ICV_DO_NORM, false);
+    miicv_setint(_icvid, MI_ICV_DO_RANGE, false);
+    
+    miicv_attach(_icvid, _mincid, _imgid);
+    
+    _io_datatype=NC_BYTE;
+    _write_prepared=true;
+  }
+  
+  void minc_1_writer::setup_write_int(bool n)
+  {
+    _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, 0, NULL);
+    _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, 0, NULL);
+    _set_image_range=true;
+    _set_slice_range=false;
+    
+    ncendef(_mincid);
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_INT);
+    miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_SIGNED);
+
+    /* Set range of values */ //TODO: set this to something sensible?
+    miicv_setint(_icvid, MI_ICV_VALID_MIN, INT_MIN);
+    miicv_setint(_icvid, MI_ICV_VALID_MAX, INT_MAX);
+
+    /* No normalization so that pixels are scaled to the slice */
+    miicv_setint(_icvid, MI_ICV_DO_NORM, false);
+    miicv_setint(_icvid, MI_ICV_DO_RANGE, false);
+    
+    miicv_attach(_icvid, _mincid, _imgid);
+
+    
+    _io_datatype=NC_INT;
+    _write_prepared=true;
+  }
+  
+  void minc_1_writer::setup_write_uint(bool n)
+  {
+    _icmax=micreate_std_variable(_mincid, (char*)MIimagemax, NC_DOUBLE, 0, NULL);
+    _icmin=micreate_std_variable(_mincid, (char*)MIimagemin, NC_DOUBLE, 0, NULL);
+    _set_image_range=true;
+    _set_slice_range=false;
+    
+    ncendef(_mincid);
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_INT);
+    miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_UNSIGNED);
+
+    /* Set range of values */ //TODO: set this to something sensible?
+    miicv_setint(_icvid, MI_ICV_VALID_MIN, 0);
+    miicv_setint(_icvid, MI_ICV_VALID_MAX, UINT_MAX);
+
+    /* No normalization so that pixels are scaled to the slice */
+    miicv_setint(_icvid, MI_ICV_DO_NORM, false);
+    miicv_setint(_icvid, MI_ICV_DO_RANGE, false);
+    
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_INT;
+    _write_prepared=true;
+  }
+  
+  void minc_1_reader::_setup_dimensions(void)
+  {
+    if(_metadate_only)
+      REPORT_ERROR("Minc file in metadate only mode!");
+    if(_positive_directions)
+    {
+      /* We want to ensure that images have X, Y and Z dimensions in the
+      positive direction, giving patient left on left and for drawing from
+      bottom up. If we wanted patient right on left and drawing from
+      top down, we would set to MI_ICV_NEGATIVE. */
+      
+      miicv_setint(_icvid, MI_ICV_DO_DIM_CONV, true);
+      //TODO: make sure to change only x,y,z conversions here
+      //miicv_setint(_icvid, MI_ICV_XDIM_DIR, 3);
+      //we want to convert only X,Y,Z dimensions if they are present
+      int num=(_map_to_std[1]>=0?1:0)+(_map_to_std[2]>=0?1:0)+(_map_to_std[3]>=0?1:0);
+      miicv_setint(_icvid, MI_ICV_NUM_IMGDIMS, num);
+      
+      if(_map_to_std[1]>=0) 
+      {
+        miicv_setint(_icvid, MI_ICV_DIM_SIZE+_map_to_std[1],-1);
+        miicv_setint(_icvid, MI_ICV_XDIM_DIR, MI_ICV_POSITIVE);
+      }
+      
+      if(_map_to_std[2]>=0) 
+      {
+        miicv_setint(_icvid, MI_ICV_DIM_SIZE+_map_to_std[2],-1);
+        miicv_setint(_icvid, MI_ICV_YDIM_DIR, MI_ICV_POSITIVE);
+      }
+      
+      if(_map_to_std[3]>=0) 
+      {
+        miicv_setint(_icvid, MI_ICV_DIM_SIZE+_map_to_std[3],-1);
+        miicv_setint(_icvid, MI_ICV_ZDIM_DIR, MI_ICV_POSITIVE);
+      }
+    }
+    miicv_setint(_icvid, MI_ICV_DO_SCALAR, false);
+  }
+  
+  void minc_1_reader::setup_read_float(void)
+  {
+    if(_metadate_only)
+      REPORT_ERROR("Minc file in metadate only mode!");
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_FLOAT);
+    miicv_setint(_icvid, MI_ICV_DO_NORM, true);
+    miicv_setint(_icvid, MI_ICV_USER_NORM, true);
+    /* Make sure that any out of range values are mapped to lowest value
+      of type (for input only) */
+    miicv_setint(_icvid, MI_ICV_DO_FILLVALUE, true);
+    
+    _setup_dimensions();
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_FLOAT;
+    _read_prepared=true;
+  }
+  
+  void minc_1_reader::setup_read_double(void)
+  {
+    if(_metadate_only)
+      REPORT_ERROR("Minc file in metadate only mode!");
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_DOUBLE);
+    miicv_setint(_icvid, MI_ICV_DO_NORM, true);
+    miicv_setint(_icvid, MI_ICV_USER_NORM, true);
+    /* Make sure that any out of range values are mapped to lowest value
+      of type (for input only) */
+    miicv_setint(_icvid, MI_ICV_DO_FILLVALUE, true);
+    
+    _setup_dimensions();
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_DOUBLE;
+    _read_prepared=true;
+  }
+
+  void minc_1_reader::setup_read_short(bool n)
+  {
+    if(_metadate_only)
+      REPORT_ERROR("Minc file in metadate only mode!");
+    
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_SHORT);
+    miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_SIGNED);
+    /* Set range of values */
+    miicv_setdbl(_icvid, MI_ICV_VALID_MIN, _image_range[0]);
+    miicv_setdbl(_icvid, MI_ICV_VALID_MAX, _image_range[1]);
+
+    /* Do normalization so that all pixels are on same scale */
+    miicv_setint(_icvid, MI_ICV_DO_NORM, true);
+    //miicv_setint(_icvid, MI_ICV_USER_NORM, true);
+    /* Make sure that any out of range values are mapped to lowest value
+      of type (for input only) */
+    miicv_setint(_icvid, MI_ICV_DO_FILLVALUE, true);
+    
+    _setup_dimensions();
+    
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_SHORT;
+    _read_prepared=true;
+  }
+  
+  void minc_1_reader::setup_read_ushort(bool n)
+  {
+    if(_metadate_only)
+      REPORT_ERROR("Minc file in metadate only mode!");
+    
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_SHORT);
+    miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_UNSIGNED);
+    /* Set range of values */
+    miicv_setdbl(_icvid, MI_ICV_VALID_MIN, _image_range[0]);
+    miicv_setdbl(_icvid, MI_ICV_VALID_MAX, _image_range[1]);
+
+    /* Do normalization so that all pixels are on same scale */
+    miicv_setint(_icvid, MI_ICV_DO_NORM, false);
+    //miicv_setint(_icvid, MI_ICV_USER_NORM, true);
+    /* Make sure that any out of range values are mapped to lowest value
+      of type (for input only) */
+    miicv_setint(_icvid, MI_ICV_DO_FILLVALUE, true);
+    
+    _setup_dimensions();
+    
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_SHORT;
+    _read_prepared=true;
+  }
+  
+  void minc_1_reader::setup_read_byte(bool n)
+  {
+    if(_metadate_only)
+      REPORT_ERROR("Minc file in metadate only mode!");
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_BYTE);
+    miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_UNSIGNED);
+    /* Set range of values */
+    miicv_setdbl(_icvid, MI_ICV_VALID_MIN, _image_range[0]);
+    miicv_setdbl(_icvid, MI_ICV_VALID_MAX, _image_range[1]);
+
+   /* Do normalization so that all pixels are on same scale */
+    miicv_setint(_icvid, MI_ICV_DO_NORM, true);
+    /* Make sure that any out of range values are mapped to lowest value
+      of type (for input only) */
+    miicv_setint(_icvid, MI_ICV_DO_FILLVALUE, true);
+    
+    _setup_dimensions();
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_BYTE;
+    _read_prepared=true;
+  }
+  
+  void minc_1_reader::setup_read_int(bool n)
+  {
+    if(_metadate_only)
+      REPORT_ERROR("Minc file in metadate only mode!");
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_INT);
+    miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_SIGNED);
+    /* Set range of values */
+    miicv_setdbl(_icvid, MI_ICV_VALID_MIN, _image_range[0]);
+    miicv_setdbl(_icvid, MI_ICV_VALID_MAX, _image_range[1]);
+
+   /* Do normalization so that all pixels are on same scale */
+    miicv_setint(_icvid, MI_ICV_DO_NORM, true);
+    /* Make sure that any out of range values are mapped to lowest value
+      of type (for input only) */
+    miicv_setint(_icvid, MI_ICV_DO_FILLVALUE, true);
+    
+    _setup_dimensions();
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_INT;
+    _read_prepared=true;
+  }
+  
+  void minc_1_reader::setup_read_uint(bool n)
+  {
+    if(_metadate_only)
+      REPORT_ERROR("Minc file in metadate only mode!");
+    miicv_setint(_icvid, MI_ICV_TYPE, NC_INT);
+    miicv_setstr(_icvid, MI_ICV_SIGN, (char*)MI_UNSIGNED);
+    /* Set range of values */
+    miicv_setdbl(_icvid, MI_ICV_VALID_MIN, _image_range[0]);
+    miicv_setdbl(_icvid, MI_ICV_VALID_MAX, _image_range[1]);
+
+   /* Do normalization so that all pixels are on same scale */
+    miicv_setint(_icvid, MI_ICV_DO_NORM, true);
+    /* Make sure that any out of range values are mapped to lowest value
+      of type (for input only) */
+    miicv_setint(_icvid, MI_ICV_DO_FILLVALUE, true);
+    
+    _setup_dimensions();
+    miicv_attach(_icvid, _mincid, _imgid);
+    _io_datatype=NC_INT;
+    _read_prepared=true;
+  }
+  
+  void minc_1_reader::read(void* buffer)
+  {
+    if(!_read_prepared)
+      REPORT_ERROR("Not ready to read, use setup_read_XXXX");
+
+    miicv_get(_icvid, &_cur[0], &_slab[0], buffer);
+  }
+  
+  void minc_1_writer::write(void* buffer)
+  {
+    if(!_write_prepared)
+      REPORT_ERROR("Not ready to write, use setup_write_XXXX");
+    
+    double r_min= DBL_MAX; //slab minimal value
+    double r_max=-DBL_MAX; //slab maximal value
+    //int irmin=0,irmax=0;
+    if(_calc_min_max )
+    {
+      if(_io_datatype==NC_FLOAT)
+      {// 
+        float *tmp=(float*)buffer;
+        for(int i=0;i<_slab_len;i++)
+        {
+          if(r_min>tmp[i]) r_min=tmp[i];//irmin=i;
+          if(r_max<tmp[i]) r_max=tmp[i];//irmax=i;
+        }
+      } else if(_io_datatype==NC_DOUBLE) {
+          double *tmp=(double*)buffer;
+          for(int i=0;i<_slab_len;i++)
+          {
+            if(r_min>tmp[i]) r_min=tmp[i];//irmin=i;
+            if(r_max<tmp[i]) r_max=tmp[i];//irmax=i;
+          }
+      } else if(_io_datatype==NC_SHORT && !_is_signed) {
+        unsigned short *tmp=(unsigned short *)buffer;
+        for(int i=0;i<_slab_len;i++)
+        {
+          if(r_min>tmp[i]) r_min=tmp[i];
+          if(r_max<tmp[i]) r_max=tmp[i];
+        }
+      } else if(_io_datatype==NC_SHORT && _is_signed) {
+        short *tmp=(short *)buffer;
+        for(int i=0;i<_slab_len;i++)
+        {
+          if(r_min>tmp[i]) r_min=tmp[i];
+          if(r_max<tmp[i]) r_max=tmp[i];
+        }
+      } else if(_io_datatype==NC_BYTE) {
+        unsigned char *tmp=(unsigned char *)buffer;
+        for(int i=0;i<_slab_len;i++)
+        {
+          if(r_min>tmp[i]) r_min=tmp[i];
+          if(r_max<tmp[i]) r_max=tmp[i];
+        }
+      } else if(_io_datatype==NC_INT && _is_signed) {
+        int *tmp=(int *)buffer;
+        for(int i=0;i<_slab_len;i++)
+        {
+          if(r_min>tmp[i]) r_min=tmp[i];
+          if(r_max<tmp[i]) r_max=tmp[i];
+        }
+      } else if(_io_datatype==NC_INT && !_is_signed) {
+        unsigned int *tmp=(unsigned int *)buffer;
+        for(int i=0;i<_slab_len;i++)
+        {
+          if(r_min>tmp[i]) r_min=tmp[i];
+          if(r_max<tmp[i]) r_max=tmp[i];
+        }
+      }
+      /*
+      if(r_min<-10000||r_max>10000)
+      {
+        std::cerr<<r_min<<":"<<r_max<<" ";
+        for(int i=0;i<4;i++)
+          std::cerr<<_cur[i]<<",";
+        std::cerr<<"  "<<r_min<<":"<<r_max;
+        std::cerr<<" "<<irmin<<":"<<irmax<<"   "<<_slab_len;
+        std::cerr<<std::endl;
+      }*/
+      
+      if(_set_slice_range)
+      {
+        miicv_detach(_icvid);
+        miicv_setdbl(_icvid, MI_ICV_VALID_MIN, r_min);
+        miicv_setdbl(_icvid, MI_ICV_VALID_MAX, r_max);
+        miicv_attach(_icvid, _mincid, _imgid);
+      }
+      
+      if(_set_slice_range)
+      {
+        mivarput1(_mincid, _icmin, &_cur[0], NC_DOUBLE, NULL, &r_min);
+        mivarput1(_mincid, _icmax, &_cur[0], NC_DOUBLE, NULL, &r_max);
+      }
+      
+      if(_image_range[0]>r_min) _image_range[0]=r_min;
+      if(_image_range[1]<r_max) _image_range[1]=r_max;
+    }
+    miicv_put(_icvid, &_cur[0], &_slab[0], buffer);
+  }
+  
+  minc_1_writer::~minc_1_writer()
+  {
+    if(_set_image_range)
+    {
+      mivarput1(_mincid, _icmin, 0, NC_DOUBLE, NULL, &_image_range[0]);
+      mivarput1(_mincid, _icmax, 0, NC_DOUBLE, NULL, &_image_range[1]);
+      miset_valid_range(_mincid, _imgid, _image_range);
+    }
+  }
+  
+  void minc_1_writer::copy_headers(const minc_1_base& src)
+  {
+    
+    //code copied from mincresample
+    int nexcluded, excluded_vars[10];
+    int varid;
+    
+    /* Create the list of excluded variables */
+    nexcluded = 0;
+    //ncopts = 0;
+
+    if ((varid=ncvarid(src.mincid(), MIxspace)) != MI_ERROR)
+      excluded_vars[nexcluded++] = varid;
+    if ((varid=ncvarid(src.mincid(), MIyspace)) != MI_ERROR)
+      excluded_vars[nexcluded++] = varid;
+    if ((varid=ncvarid(src.mincid(), MIzspace)) != MI_ERROR)
+      excluded_vars[nexcluded++] = varid;
+    if ((varid=ncvarid(src.mincid(), MItime)) != MI_ERROR)
+      excluded_vars[nexcluded++] = varid;
+    if ((varid=ncvarid(src.mincid(), MIimage)) != MI_ERROR)
+      excluded_vars[nexcluded++] = varid;
+    if ((varid=ncvarid(src.mincid(), MIimagemax)) != MI_ERROR)
+      excluded_vars[nexcluded++] = varid;
+    if ((varid=ncvarid(src.mincid(), MIimagemin)) != MI_ERROR)
+      excluded_vars[nexcluded++] = varid;
+    if ((varid=ncvarid(src.mincid(), "rootvariable")) != MI_ERROR)
+      excluded_vars[nexcluded++] = varid;
+//#if MINC2
+    if ((varid=ncvarid(src.mincid(), MIvector_dimension)) != MI_ERROR)
+      excluded_vars[nexcluded++] = varid;
+//#endif /* MINC2 */
+    //ncopts = NC_VERBOSE | NC_FATAL;
+    /* Copy all other variable definitions */
+    micopy_all_var_defs(src.mincid(), _mincid, nexcluded, excluded_vars);
+  }
+  
+  //! append a line into minc history
+  void minc_1_writer::append_history(const char *append_history)
+  {
+    nc_type datatype;
+    int att_length;
+    //ncopts=0;
+    if ((ncattinq(_mincid, NC_GLOBAL, MIhistory, &datatype,&att_length) == MI_ERROR) ||
+        (datatype != NC_CHAR))
+      att_length = 0;
+    att_length += strlen(append_history) + 1;
+    char* str = new char[att_length];
+    str[0] = '\0';
+    miattgetstr(_mincid, NC_GLOBAL, (char*)MIhistory, att_length,str);
+    //ncopts=NC_VERBOSE | NC_FATAL;
+    strcat(str, append_history);
+    miattputstr(_mincid, NC_GLOBAL, (char*)MIhistory, str);
+    delete [] str;
+  }
+  
+  int minc_1_base::create_var_id(const char *varname)
+  {
+    int old_ncopts = ncopts; ncopts = 0;
+    int res=var_id(varname);
+    if(res==MI_ERROR) //need to create a variable
+      res=micreate_group_variable(_mincid,(char*)varname);//ncvardef(_mincid,varname,NC_INT,0,0);
+    if(res==MI_ERROR) //need to create a variable
+      res=ncvardef(_mincid,varname,NC_INT,0,0);
+    ncopts = old_ncopts;
+    return res;
+  }
+      
+  void minc_1_base::insert(const char *varname,const char *attname,double val)
+  {
+    ncattput(_mincid, create_var_id(varname),attname, NC_DOUBLE, 1, (void *) &val);
+  }
+  
+  void minc_1_base::insert(const char *varname,const char *attname,const char* val)
+  {
+    ncattput(_mincid, create_var_id(varname),attname, NC_CHAR, strlen(val) + 1, (void *) val);
+  }
+  
+  void minc_1_base::insert(const char *varname,const char *attname,const std::vector<double> &val)
+  {
+    ncattput(_mincid, create_var_id(varname),attname, NC_DOUBLE, val.size(), (void *) &val[0]);
+  }
+  
+  void minc_1_base::insert(const char *varname,const char *attname,const std::vector<int> &val)
+  {
+    ncattput(_mincid, create_var_id(varname),attname, NC_INT, val.size(), (void *) &val[0]);
+  }
+  
+  void minc_1_base::insert(const char *varname,const char *attname,const std::vector<short> &val)
+  {
+    ncattput(_mincid, create_var_id(varname),attname, NC_SHORT, val.size(), (void *) &val[0]);
+  }
+  
+  void minc_1_base::insert(const char *varname,const char *attname,const std::vector<unsigned char> &val)
+  {
+    ncattput(_mincid, create_var_id(varname),attname, NC_BYTE, val.size(), (void *) &val[0]);
+  }
+  
+};
new file mode 100644
--- /dev/null
+++ b/ezminc/minc_1_rw.h
@@ -0,0 +1,391 @@
+#ifndef __MINC_1_RW__
+#define __MINC_1_RW__
+
+#include <vector>
+#include <string>
+
+#include "minc_io_exceptions.h"
+//#include "minc_io_fixed_vector.h"
+
+#ifdef USE_MINC2
+#define MINC2 1
+#endif 
+
+extern "C" {
+#include <minc.h> 
+}
+
+#include <typeinfo>
+#include <float.h>
+#include <iostream>
+
+namespace minc
+{
+  
+  //! class for storing dimension information 
+  struct dim_info
+  {
+    enum dimensions {DIM_UNKNOWN=0,DIM_X,DIM_Y,DIM_Z,DIM_TIME,DIM_VEC} ;
+    dim_info():length(0),step(0),start(0),have_dir_cos(false)
+    {
+      dir_cos[0]=dir_cos[1]=dir_cos[2]=0.0;
+    }
+    dim_info(int l, double sta,double spa,dimensions d,bool hd=false);
+    size_t length;
+    double step,start;
+    bool have_dir_cos;
+    double dir_cos[3];
+    std::string name;
+    dimensions  dim;
+  };
+  
+  //! collection of dimensions describing a minc file
+  typedef std::vector<dim_info> minc_info;
+  
+  //! minc file rw base class
+  class minc_1_base
+  {
+  protected:
+    int _slab_len;
+    int _icvid;
+    std::vector<long> _cur,_slab;
+    size_t  _slice_dimensions;
+    bool _last;
+    bool _positive_directions;
+    nc_type _datatype;
+    nc_type _io_datatype;
+    char _dimension_names[MAX_VAR_DIMS][MAX_NC_NAME];
+    std::vector<double> _dir_cos;
+    long vcount[MAX_VAR_DIMS];
+    std::vector<double> _world_matrix;
+    std::vector<int>    _voxel_matrix;
+    int _ndims, mdims[MAX_VAR_DIMS];
+    int _is_signed;
+    int _mincid, _imgid;
+    int _icmax,_icmin;
+    double _image_range[2];
+    std::vector<long> _dims;
+    std::vector<int> _map_to_std;
+    minc_info _info;
+    bool _minc2;
+  public:
+    
+    //! get the minc handle
+    int mincid(void) const  //this is not really a const ?
+    {
+      return _mincid;
+    }
+    
+    //! get the data type id (NC_BYTE,NC_INT etc)
+    nc_type datatype(void) const
+    {
+      return _datatype;
+    }
+    
+    //! byte size of the volume elements
+    unsigned int element_size(void) const
+    {
+      switch(_io_datatype)
+      {
+        case NC_FLOAT: return sizeof(float);
+        case NC_DOUBLE: return sizeof(double);
+        case NC_SHORT: return sizeof(short);
+        case NC_BYTE: return sizeof(char);
+        default:return 0;//maybe throw exception here?
+      }
+    }
+    
+    //! is data stored in signed format
+    bool is_signed(void) const
+    {
+      return _is_signed;
+    }
+  
+    //! constructor
+	  minc_1_base();
+
+    //! destructor, closes minc file
+    virtual ~minc_1_base();
+    
+    //! close the minc file
+    virtual void close();
+
+    //! is last slice was read?
+    bool last(void) const 
+    {
+      return _last;
+    }
+    
+    //! go to the beginning of file
+    void begin(void)
+    {
+      fill(_cur.begin(),_cur.end(),0);
+      _last=false;
+    }
+    
+    //! advance to next slice 
+    bool next_slice(void)
+    {
+      if(_last) return !_last;
+        
+      for(int i=_ndims-_slice_dimensions-1;i>=0;i--)
+      {
+        _cur[i]++;
+        if(_cur[i]<static_cast<long>(_info[i].length))
+          break;
+        if(!i)
+          _last=true;
+        else 
+          _cur[i]=0;
+      }
+      return !_last;
+    }
+    
+    //! slice length in elements
+    int slice_len(void) const
+    {
+      return _slab_len;
+    }
+    
+    //! number of dimensions
+    int dim_no(void) const
+    {
+      return _ndims;
+    }
+    
+    //! get the dimension information
+    const dim_info& dim(unsigned int n) const
+    {
+      if(n>=static_cast<unsigned int>(_ndims)) 
+	REPORT_ERROR("Dimension is not defined");
+      return _info[n];
+    }
+    
+    //! get the pointer to the dimension description array
+    const minc_info& info(void) const
+    {
+      return _info;
+    }
+    
+    //! get the number of dimensions in one slice
+    int slice_dimensions(void) const
+    {
+      return _slice_dimensions;
+    }
+    
+    //! get the current slice index
+    const std::vector<long> & current_slice(void) const
+    {
+      return _cur;
+    }
+    
+    //! get the normalized dimensions sizes 
+    //! ( 0 - vector_dimension, 1 - x, 2- y , 3 -z , 4 - time)
+    int ndim(int i) const
+    {
+      int j=_map_to_std[i];
+      if(j>=0) return _info[j].length;
+      return 0;
+    }
+    //! get normalized dimension start coordinate (see ndim)
+    double nstart(int i) const
+    {
+      int j=_map_to_std[i];
+      if(j>=0) return _info[j].start;
+      return 0.0;
+    }
+    
+    //! get normalized dimension spacing  (see ndim)
+    double nspacing(int i) const
+    {
+      int j=_map_to_std[i];
+      if(j>=0) return _info[j].step;
+      return 0.0;
+    }
+    
+    //! get normalized dimension direction cosine component  (see ndim)
+    double ndir_cos(int i,int j) const
+    {
+      int k=_map_to_std[i];
+      if(k>=0) return _info[k].dir_cos[j];
+      return 0.0;
+    }
+    
+    //! check if a normalized dimension has direction cosine information
+    bool have_dir_cos(int i) const
+    {
+      int k=_map_to_std[i];
+      if(k>=0) return _info[k].have_dir_cos;
+      return false;
+    }
+     
+    //! map file dimensions into normalized dimensions
+    int map_space(int i)
+    {
+      return _map_to_std[i];
+    }
+    
+    //metadate info handling function:
+    //! read the minc history (:history attribute)
+    std::string history(void) const;
+    
+    //! retrive var id, if it exists, otherwise return MI_ERROR
+    int var_id(const char *var_name) const;
+    
+    //! get variable length
+    long var_length(const char *var_name) const;
+    
+    //! get variable length
+    long var_length(int var_id) const;
+    
+    //! read the number of variables
+    int var_number(void) const;
+    
+    //! get the variable name number no
+    std::string var_name(int no) const;
+    
+    //! get the number of attributes associated with variable
+    int att_number(const char *var_name) const;
+    
+    //! get the number of attributes associated with variable
+    int att_number(int var_no) const;
+    
+    //! get the attribute name, given the number
+    std::string att_name(const char *var_name,int no) const;
+    //! get the attribute name, given the number
+    std::string att_name(int varid,int no) const;
+    
+    //! get the string attribute value , given the name
+    std::string att_value_string(const char *var_name,const char *att_name) const;
+    //! get the string attribute value , given variable id
+    std::string att_value_string(int varid,const char *att_name) const;
+    
+    //! get the double attribute value , given the name
+    std::vector<double> att_value_double(const char *var_name,const char *att_name) const;
+    //! get the int attribute value , given the name
+    std::vector<int> att_value_int(const char *var_name,const char *att_name) const;
+    //! get the short attribute value , given the variable id
+    std::vector<short> att_value_short(const char *var_name,const char *att_name) const;
+    //! get the byte attribute value , given the variable id
+    std::vector<unsigned char> att_value_byte(const char *var_name,const char *att_name) const;
+    
+    //! get the double attribute value , given the variable id
+    std::vector<double> att_value_double(int varid,const char *att_name) const;
+    //! get the int attribute value , given the variable id
+    std::vector<int> att_value_int(int varid,const char *att_name) const;
+    //! get the short attribute value , given the variable id
+    std::vector<short> att_value_short(int varid,const char *att_name) const;
+    //! get the byte attribute value , given the variable id
+    std::vector<unsigned char> att_value_byte(int varid,const char *att_name) const;
+    
+    //! enquire about attribute data type
+    nc_type att_type(const char *var_name,const char *att_name) const;
+    //! enquire about attribute data type
+    nc_type att_type(int varid,const char *att_name) const;
+
+    //! enquire about attribute length
+    int att_length(const char *var_name,const char *att_name) const;
+    //! enquire about attribute length
+    int att_length(int varid,const char *att_name) const;
+
+
+    //! return var_id for the given name (create one, if it doesn't exists)
+    int create_var_id(const char *varname);
+    
+    void insert(const char *varname,const char *attname,double val);
+    void insert(const char *varname,const char *attname,const char* val);
+    void insert(const char *varname,const char *attname,const std::vector<double> &val);
+    void insert(const char *varname,const char *attname,const std::vector<int> &val);
+    void insert(const char *varname,const char *attname,const std::vector<short> &val);
+    void insert(const char *varname,const char *attname,const std::vector<unsigned char> &val);
+    
+    
+    //! check if the file in MINC2 format
+    bool is_minc2(void) const
+    {
+      return _minc2;
+    }
+    
+  };
+  
+  //! minc file reader
+  class minc_1_reader:public minc_1_base
+  {
+    protected:
+      bool _metadate_only;
+      std::string _tempfile;
+      bool _have_temp_file;
+      bool _read_prepared;
+      void _setup_dimensions(void);
+
+    public:
+    //! copy constructor
+    minc_1_reader(const minc_1_reader&);
+    
+    //! default constructor
+    minc_1_reader();
+    
+    //! destructor
+    virtual ~minc_1_reader();
+    //! open a minc file
+    void open(const char *path,bool positive_directions=false,bool metadate_only=false,bool rw=false);
+    
+    //! read single slice
+    void read(void* slice);
+    //! setup reading in float format
+    void setup_read_float(void);
+    //! setup reading in double format
+    void setup_read_double(void);
+    //! setup reading in signed short format
+    void setup_read_short(bool normalized=false);
+    //! setup reading in unsigned short format
+    void setup_read_ushort(bool normalized=false);
+    //! setup reading in byte format
+    void setup_read_byte(bool normalized=false);
+    //! setup reading in int format
+    void setup_read_int(bool normalized=false);
+    //! setup reading in unsigned int format
+    void setup_read_uint(bool normalized=false);
+  };
+  
+  //! minc file writer
+  class minc_1_writer:public minc_1_base
+  {
+    protected:
+      bool _set_image_range;
+      bool _set_slice_range;
+      bool _calc_min_max;
+      bool _write_prepared;
+    public:
+      void open(const char *path,const minc_info& inf,int slice_dimensions,nc_type datatype,int __signed=0);
+      void open(const char *path,const minc_1_base& imitate);
+      void open(const char *path,const char *imitate_file);
+    
+      void setup_write_float(void);
+      void setup_write_double(void);
+      void setup_write_short(bool normalize=false);
+      void setup_write_ushort(bool normalize=false);
+      void setup_write_byte(bool normalize=false);
+      void setup_write_int(bool normalize=false);
+      void setup_write_uint(bool normalize=false);
+    
+      //! copy header from another minc file
+      void copy_headers(const minc_1_base& src);
+    
+      //! append a line into minc history
+      void append_history(const char *append_history);
+      
+      
+      //! constructor
+      minc_1_writer();
+      
+      minc_1_writer(const minc_1_writer&);
+      
+      //! destructor
+      virtual ~minc_1_writer();
+      
+      //!write a single slice, size of the buffer should be more or equall to slab_len
+      void write(void* slice);
+  };
+};
+#endif //__PRIMITIVE_MINC_IO__
new file mode 100644
--- /dev/null
+++ b/ezminc/minc_1_simple.h
@@ -0,0 +1,290 @@
+#ifndef __MINC_1_SIMPLE_H__
+#define __MINC_1_SIMPLE_H__
+
+#include "minc_1_rw.h"
+
+namespace minc
+{
+  
+  template <class T> class minc_input_iterator
+  {
+    protected:
+      mutable minc_1_reader* _rw;
+      std::vector<T> _buf;
+      std::vector<long> _cur;
+      bool _last;
+      size_t _count;
+    public:
+      
+    const std::vector<long>& cur(void) const
+    {
+      return _cur;
+    }
+    
+    
+    minc_input_iterator(const minc_input_iterator<T>& a):_rw(a._rw),_cur(a._cur),_last(a._last),_count(a._count)
+    {
+    }
+    
+    minc_input_iterator(minc_1_reader& rw):_rw(&rw),_last(false),_count(0)
+    {
+    }
+    
+    minc_input_iterator():_rw(NULL),_last(false),_count(0)
+    {
+    }
+    
+    void attach(minc_1_reader& rw)
+    {
+      _rw=&rw;
+      _last=false;
+      _count=0;
+    }
+    
+    bool next(void)
+    {
+      if(_last) return false;
+      _count++;
+      for(size_t i=static_cast<size_t>(_rw->dim_no()-1);
+	  i>static_cast<size_t>(_rw->dim_no()-_rw->slice_dimensions()-1);i--)
+      {
+        _cur[i]++;
+        if(_cur[i]<static_cast<long>(_rw->dim(i).length))
+          break;
+        if(i>static_cast<size_t>(_rw->dim_no()-_rw->slice_dimensions())) 
+          _cur[i]=0;
+        else
+        {
+          //move to next slice 
+          if(i==0) // the case when slice_dimensions==dim_no
+          {
+            _last=true;
+            _count=0;
+            break;
+          }
+          if(!_rw->next_slice())
+          {
+            _last=true;
+            break;
+          }
+          _rw->read(&_buf[0]);
+          _cur=_rw->current_slice();
+          _count=0;
+          break;
+        }
+      }
+      return !_last;
+    }
+    
+    bool last(void)
+    {
+      return _last;
+    }
+    
+    void begin(void)
+    {
+      _cur.resize(MAX_VAR_DIMS,0);
+      _buf.resize(_rw->slice_len());
+      _count=0;
+      _rw->begin();
+      _rw->read(&_buf[0]);
+      _cur=_rw->current_slice();
+    }
+    
+    const T& value(void) const
+    {
+      return _buf[_count];
+    }
+  };
+  
+  template <class T> class minc_output_iterator
+  {
+    protected:
+      mutable minc_1_writer* _rw;
+      std::vector<T> _buf;
+      std::vector<long> _cur;
+      bool _last;
+      size_t _count;
+    public:
+    const std::vector<long>& cur(void) const
+    {
+      return _cur;
+    }
+    
+    minc_output_iterator(const minc_output_iterator<T>& a):_rw(a._rw),_cur(a._cur),_last(a._last),_count(a._count)
+    {
+    }
+    
+    minc_output_iterator(minc_1_writer& rw):_rw(&rw),_last(false),_count(0)
+    {
+      _buf.resize(rw.slice_len()); 
+    }
+    
+    minc_output_iterator():_rw(NULL),_last(false),_count(0)
+    {
+    }
+    
+    void attach(minc_1_writer& rw)
+    {
+      _rw=&rw;
+      _last=false;
+      _count=0;
+    }
+    
+    ~minc_output_iterator()
+    {
+      if(_count && !_last)
+        _rw->write(&_buf[0]);
+    }
+    
+    bool next(void)
+    {
+      if(_last) return false;
+      _count++;
+      for(int i=_rw->dim_no()-1;i>(_rw->dim_no()-_rw->slice_dimensions()-1);i--)
+      {
+        _cur[i]++;
+        if(_cur[i]<static_cast<long>(_rw->dim(i).length))
+          break;
+        if(i>(_rw->dim_no()-_rw->slice_dimensions())) 
+          _cur[i]=0;
+        else
+        {
+          //write slice into minc file
+          _rw->write(&_buf[0]);
+          _count=0;
+          //move to next slice 
+          if(i==0) // the case when slice_dimensions==dim_no
+          {
+            _last=true;
+            return false;
+          }
+          if(!_rw->next_slice())
+          {
+            _last=true;
+            break;
+          }
+          _cur=_rw->current_slice();
+          break;
+        }
+      }
+      return !_last;
+    }
+    
+    bool last(void)
+    {
+      return _last;
+    }
+    
+    void begin(void)
+    {
+      _buf.resize(_rw->slice_len());
+      _cur.resize(MAX_VAR_DIMS,0);
+      _count=0;
+      _rw->begin();
+      _cur=_rw->current_slice();
+    }
+    
+    void value(const T& v) 
+    {
+      _buf[_count]=v;
+    }
+  };
+  
+  //! will attempt to laod the whole volume in T Z Y X V order into buffer, file should be prepared (setup_read_XXXX)
+  template<class T> void load_standard_volume(minc_1_reader& rw, T* volume)
+  {
+    std::vector<size_t> strides(MAX_VAR_DIMS,0);
+    size_t str=1;
+    for(size_t i=0;i<5;i++)
+    {      
+      if(rw.map_space(i)<0) continue;
+      strides[rw.map_space(i)]=str;
+      str*=rw.ndim(i);
+    }
+
+    minc_input_iterator<T> in(rw);
+    for(in.begin();!in.last();in.next())
+    {
+      size_t address=0;
+      for(size_t i=0;i<static_cast<size_t>(rw.dim_no());i++)
+        address+=in.cur()[i]*strides[i];
+        
+      volume[address]=in.value();
+    }
+  }
+  
+  //! will attempt to save the whole volume in T Z Y X V order from buffer, file should be prepared (setup_read_XXXX)
+  template<class T> void save_standard_volume(minc_1_writer& rw, const T* volume)
+  {
+    std::vector<size_t> strides(MAX_VAR_DIMS,0);
+    size_t str=1;
+    for(size_t i=0;i<5;i++)
+    {      
+      if(rw.map_space(i)<0) continue;
+      strides[rw.map_space(i)]=str;
+      str*=rw.ndim(i);
+    }
+    
+    minc_output_iterator<T> out(rw);
+    for(out.begin();!out.last();out.next())
+    {
+      size_t address=0;
+      for(size_t i=0;i<static_cast<size_t>(rw.dim_no());i++)
+        address+=out.cur()[i]*strides[i];
+        
+      out.value(volume[address]);
+    }
+  }
+
+  //! will attempt to load the whole volume in Z Y X T V  order into buffer, file should be prepared (setup_read_XXXX)
+  template<class T> void load_non_standard_volume(minc_1_reader& rw, T* volume)
+  {
+    std::vector<size_t> strides(MAX_VAR_DIMS,0);
+    size_t str=1;
+    const size_t dimorder[]={0,4,1,2,3};
+    for(size_t i=0;i<5;i++)
+    {
+      if(rw.map_space(dimorder[i])<0|| !rw.ndim(dimorder[i]) ) continue;
+      strides[rw.map_space(dimorder[i])]=str;
+      str*=rw.ndim(dimorder[i]);
+    }
+    
+    minc_input_iterator<T> in(rw);
+    for(in.begin();!in.last();in.next())
+    {
+      size_t address=0;
+      for(size_t i=0;i<rw.dim_no();i++)
+        address+=in.cur()[i]*strides[i];
+      
+      volume[address]=in.value();
+    }
+  }
+  
+  //! will attempt to save the whole volume in V T Z Y X order from buffer, file should be prepared (setup_read_XXXX)
+  template<class T> void save_non_standard_volume(minc_1_writer& rw, const T* volume)
+  {
+    std::vector<size_t> strides(MAX_VAR_DIMS,0);
+    size_t str=1;
+    const size_t dimorder[]={0,4,1,2,3};
+    for(size_t i=0;i<5;i++)
+    {
+      if(rw.map_space(dimorder[i])<0 || !rw.ndim(dimorder[i]) ) continue;
+      strides[rw.map_space(dimorder[i])]=str;
+      str*=rw.ndim(dimorder[i]);
+    }
+    minc_output_iterator<T> out(rw);
+    for(out.begin();!out.last();out.next())
+    {
+      size_t address=0;
+      for(size_t i=0;i<rw.dim_no();i++)
+        address+=out.cur()[i]*strides[i];
+
+      out.value(volume[address]);
+    }
+  }
+  
+  
+};//minc
+
+#endif //__MINC_1_SIMPLE_H__
new file mode 100644
--- /dev/null
+++ b/ezminc/minc_1_simple_rw.cpp
@@ -0,0 +1,53 @@
+#include <iostream>
+#include <math.h>
+
+#include "minc_1_simple_rw.h"
+
+namespace minc
+{
+
+  const double minc_eps=1e-5;
+  
+  bool is_same(minc_1_reader& one,minc_1_reader& two,bool verbose)
+  {
+    if(one.dim_no()!=two.dim_no())
+    {
+      if(verbose)
+        std::cerr<<"Unequal number of dimensions !"<<std::endl;
+      return false;
+    }
+    for(int j=0;j<5;j++)
+    {
+      if(one.ndim(j)!=two.ndim(j))
+      {
+        if(verbose)
+          std::cerr<<"Unequal dimension sizes"<<std::endl;
+        return false;
+      }
+      
+      if(fabs(one.nstart(j)-two.nstart(j))>minc_eps)
+      {
+        if(verbose)
+          std::cerr<<"Unequal dimension sarts"<<std::endl;
+        return false;
+      }
+      
+      if(fabs(one.nspacing(j)-two.nspacing(j))>minc_eps)
+      {
+        if(verbose)
+          std::cerr<<"Unequal dimension steps"<<std::endl;
+        return false;
+      }
+      
+      for(int i=0;i<3;i++)
+        if(fabs(one.ndir_cos(j,i)-two.ndir_cos(j,i))>minc_eps)
+        {
+          if(verbose)
+            std::cerr<<"Unequal direction cosines"<<std::endl;
+          return false;
+        }
+    }
+    return true;
+  }
+
+};
new file mode 100644
--- /dev/null
+++ b/ezminc/minc_1_simple_rw.h
@@ -0,0 +1,334 @@
+#ifndef __MINC_1_SIMPLE_RW_H__
+#define __MINC_1_SIMPLE_RW_H__
+
+#include "minc_1_simple.h"
+#include "minc_io_simple_volume.h"
+#include "minc_io_fixed_vector.h"
+#include "minc_io_4d_volume.h"
+
+namespace minc
+{
+  
+  template<class T> void load_simple_volume(minc_1_reader& rw,simple_volume<T>& vol)
+  {
+    if(rw.ndim(1)<=0||rw.ndim(2)<=0||rw.ndim(3)<=0||rw.ndim(4)>0) 
+      REPORT_ERROR("Need 3D minc file");
+    
+    vol.resize(rw.ndim(1),rw.ndim(2),rw.ndim(3));
+     
+    if(typeid(T)==typeid(unsigned char))
+    {
+      rw.setup_read_byte();
+      load_standard_volume(rw,vol.c_buf());
+    }
+    else if(typeid(T)==typeid(int))
+    {
+      rw.setup_read_int();
+      load_standard_volume(rw,vol.c_buf());
+    }
+    else if(typeid(T)==typeid(fixed_vec<3,float>))
+    {
+      rw.setup_read_float(); 
+      load_standard_volume<float>(rw,(float*)vol.c_buf());
+    }
+    else if(typeid(T)==typeid(float))
+    {
+      rw.setup_read_float(); 
+      load_standard_volume(rw,vol.c_buf());
+    }
+    else if(typeid(T)==typeid(fixed_vec<3,double>))
+    {
+      rw.setup_read_double(); 
+      load_standard_volume<double>(rw,(double*)vol.c_buf());
+    }
+    else if(typeid(T)==typeid(double))
+    {
+      rw.setup_read_double(); 
+      load_standard_volume(rw,vol.c_buf());
+    } else 
+			REPORT_ERROR("Data type not supported for minc io");
+    
+    //set coordinate transfer parameters
+    for(int i=0;i<3;i++)
+    {
+      vol.step()[i]=rw.nspacing(i+1);
+      vol.start()[i]=rw.nstart(i+1);
+      
+      if(rw.have_dir_cos(i+1))
+      {
+        for(int j=0;j<3;j++)
+          vol.direction_cosines(i)[j]=rw.ndir_cos(i+1,j);
+      } else {
+        for(int j=0;j<3;j++)
+          vol.direction_cosines(i)[j]=(i==j?1.0:0.0); //identity
+      }
+    }
+  }
+  
+  template<class T> void save_simple_volume(minc_1_writer& rw,const simple_volume<T>& vol)
+  {
+    if(typeid(T)==typeid(unsigned char))
+    {
+      rw.setup_write_byte();
+      save_standard_volume(rw,vol.c_buf());
+    }
+    else if(typeid(T)==typeid(int))
+    {
+      rw.setup_write_int();
+      save_standard_volume(rw,vol.c_buf());
+    }
+    else if(typeid(T)==typeid(fixed_vec<3,float>))
+    {
+      rw.setup_write_float(); 
+      save_standard_volume<float>(rw,(float*)vol.c_buf());
+    }
+    else if(typeid(T)==typeid(float))
+    {
+      rw.setup_write_float(); 
+      save_standard_volume(rw,vol.c_buf());
+    }
+    else if(typeid(T)==typeid(fixed_vec<3,double>))
+    {
+      rw.setup_write_double(); 
+      save_standard_volume<double>(rw,(double*)vol.c_buf());
+    }
+    else if(typeid(T)==typeid(double))
+    {
+      rw.setup_write_double(); 
+      save_standard_volume(rw,vol.c_buf());
+    }
+    else 
+			REPORT_ERROR("Data type not supported for minc io");
+  }
+  
+  
+  template<class T> void load_4d_volume(minc_1_reader& rw,simple_4d_volume<T>& vol)
+  {
+    //if(rw.ndim(1)<=0||rw.ndim(2)<=0||rw.ndim(3)<=0||rw.ndim(4)<=0) 
+    //  REPORT_ERROR("Need 4D minc file");
+    
+    vol.resize(rw.ndim(1),rw.ndim(2),rw.ndim(3),rw.ndim(4)>0?rw.ndim(4):1); //always assume 4 dimensions
+     
+    if(typeid(T)==typeid(unsigned char))
+      rw.setup_read_byte();
+    else if(typeid(T)==typeid(int))
+      rw.setup_read_int();
+    else if(typeid(T)==typeid(fixed_vec<3,float>))
+      rw.setup_read_float(); 
+    else if(typeid(T)==typeid(float))
+      rw.setup_read_float(); 
+    else if(typeid(T)==typeid(fixed_vec<3,double>))
+      rw.setup_read_double(); 
+    else if(typeid(T)==typeid(double))
+      rw.setup_read_double();
+		else 
+			REPORT_ERROR("Data type not supported for minc io");
+    
+    std::vector<size_t> strides(MAX_VAR_DIMS,0);
+    size_t str=1;
+    
+    for(size_t i=0;i<5;i++) //T is a special case
+    {      
+      if(rw.map_space(i)<0) continue;
+      strides[rw.map_space(i)]=str;
+      str*=rw.ndim(i);
+    }
+    
+    if(rw.map_space(4)>=0)
+      strides[rw.map_space(4)]=0; //t dimension
+
+    minc_input_iterator<T> in(rw);
+    for(in.begin();!in.last();in.next())
+    {
+      size_t address=0;
+      size_t slice=0;
+      for(size_t i=0;i<rw.dim_no();i++)
+      {
+        if(strides[i]>0)
+          address+=in.cur()[i]*strides[i];
+        else //
+          slice=in.cur()[i];
+      }
+      vol.frame(slice).c_buf()[address]=in.value();
+    }
+    
+    //set coordinate transfer parameters
+    for(int i=0;i<3;i++)
+    {
+      vol.step()[i]=rw.nspacing(i+1);
+      vol.start()[i]=rw.nstart(i+1);
+      
+      if(rw.have_dir_cos(i+1))
+      {
+        for(int j=0;j<3;j++)
+          vol.direction_cosines(i)[j]=rw.ndir_cos(i+1,j);
+      } else {
+        for(int j=0;j<3;j++)
+          vol.direction_cosines(i)[j]=(i==j?1.0:0.0); //identity
+      }
+    }
+    if(rw.ndim(4)>0)
+    {
+      vol.t_start()=rw.nstart(4);//T
+      vol.t_step()=rw.nspacing(4);//T
+    } else {
+      vol.t_start()=0;//T
+      vol.t_step()=0;//T
+    }
+  }
+  
+  template<class T> void save_4d_volume(minc_1_writer& rw,const simple_4d_volume<T>& vol)
+  {
+    if(typeid(T)==typeid(unsigned char))
+      rw.setup_write_byte();
+    else if(typeid(T)==typeid(int))
+      rw.setup_write_int();
+    else if(typeid(T)==typeid(fixed_vec<3,float>))
+      rw.setup_write_float(); 
+    else if(typeid(T)==typeid(float))
+      rw.setup_write_float(); 
+    else if(typeid(T)==typeid(fixed_vec<3,double>))
+      rw.setup_write_double(); 
+    else if(typeid(T)==typeid(double))
+      rw.setup_write_double(); 
+    else 
+			REPORT_ERROR("Data type not supported for minc io"); 
+		
+    std::vector<size_t> strides(MAX_VAR_DIMS,0);
+    size_t str=1;
+    for(size_t i=0;i<4;i++)//T is a special
+    {      
+      if(rw.map_space(i)<0) continue;
+      strides[rw.map_space(i)]=str;
+      str*=rw.ndim(i);
+    }
+    
+    if(rw.map_space(4)>=0)
+      strides[rw.map_space(4)]=0; //t dimension
+    
+    minc_output_iterator<T> out(rw);
+    for(out.begin();!out.last();out.next())
+    {
+      size_t address=0;
+      size_t slice=0;
+      for(size_t i=0;i<rw.dim_no();i++)
+      {
+        if(strides[i]>0)
+          address+=out.cur()[i]*strides[i];
+        else //
+          slice=out.cur()[i];
+      }
+      out.value(vol.frame(slice).c_buf()[address]);
+    }
+  }
+  
+  bool is_same(minc_1_reader& one,minc_1_reader& two,bool verbose=true);
+  
+  template<class T> void load_minc_file(const char *file,simple_4d_volume<T>& vol)
+  {
+      minc_1_reader rdr;
+      rdr.open(file);
+      load_4d_volume(rdr,vol);  
+  }
+  
+  template<class T> void generate_info(const simple_4d_volume<T>& vol,minc_info& info)
+  {
+     bool have_time=vol.frames()>1||vol.t_step()!=0.0; //assume that it is 3D file otherwise
+     
+     bool is_vector=false;
+      
+      if(typeid(T)==typeid(fixed_vec<3,float>)) {
+        is_vector=true;
+      } 
+      
+      info.resize(3+(is_vector?1:0)+(have_time?1:0));
+      
+      if(is_vector)
+      {
+        info[0].dim=dim_info::DIM_VEC;
+        info[0].length=3;
+        info[0].step=1;
+        
+      }
+      
+      for(int i=0;i<3;i++)
+      {
+        int ii=i+(is_vector?1:0);
+        info[ii].dim=dim_info::dimensions( dim_info::DIM_X+i);
+        
+        info[ii].length=vol.dim(i);
+        info[ii].step  =vol.step()[i];
+        info[ii].start =vol.start()[i];
+        info[ii].have_dir_cos=true;
+        
+        for(int j=0;j<3;j++)
+          info[ii].dir_cos[j]=vol.direction_cosines(i)[j];
+      }
+      
+      if(have_time) 
+      {
+        info[3+(is_vector?1:0)].dim=dim_info::DIM_TIME;
+        info[3+(is_vector?1:0)].step=vol.t_step();
+        info[3+(is_vector?1:0)].start=vol.t_start();
+        info[3+(is_vector?1:0)].length=vol.frames();
+      }
+          
+  }
+  
+  template<class T> void save_minc_file(const char *file,const simple_4d_volume<T>& vol,
+                                        const char* history=NULL,const minc_1_reader* original=NULL,
+                                        nc_type datatype=NC_NAT,bool is_signed=false)
+  {
+      minc_1_writer wrt;
+      //convert parameters to info
+      
+      if(typeid(T)==typeid(unsigned char))
+      {
+        if(datatype==NC_NAT) datatype=NC_BYTE;
+        
+      } else if(typeid(T)==typeid(int)) {
+        if(datatype==NC_NAT) datatype=NC_INT;
+        
+        is_signed=true;
+      } else if(typeid(T)==typeid(unsigned int))  {
+        if(datatype==NC_NAT) datatype=NC_INT;
+        
+        is_signed=false;
+      } else if(typeid(T)==typeid(float))  {
+        if(datatype==NC_NAT) datatype=NC_FLOAT;
+        
+        is_signed=true;
+      } else if(typeid(T)==typeid(fixed_vec<3,float>)) {
+        if(datatype==NC_NAT) datatype=NC_FLOAT;
+        
+        is_signed=true;
+      } else if(typeid(T)==typeid(double))  {
+        if(datatype==NC_NAT) datatype=NC_DOUBLE;
+        
+        is_signed=true;
+      } else if(typeid(T)==typeid(fixed_vec<3,double>)) {
+        if(datatype==NC_NAT) datatype=NC_DOUBLE;
+        
+        is_signed=true;
+      } else
+        REPORT_ERROR("Unsupported data type!");
+      
+      minc_info info;
+      generate_info<T>(vol,info);
+      
+      wrt.open(file,info,2,datatype,is_signed);
+      
+      if(original)
+      {
+        wrt.copy_headers(*original);
+      }
+      
+      if(history)
+        wrt.append_history(history);
+      
+      save_4d_volume(wrt,vol);
+  }
+  
+};
+
+#endif //__MINC_1_SIMPLE_RW_H__
new file mode 100644
--- /dev/null
+++ b/ezminc/minc_io_4d_volume.h
@@ -0,0 +1,157 @@
+#ifndef __MINC_IO_4D_VOLUME_H_
+
+#include "minc_io_simple_volume.h"
+#include <vector>
+#include <cstring>
+
+namespace minc
+{
+  
+  //! simple 4D volume - collection of 3D volumes
+  template<class T> class simple_4d_volume
+  {
+    protected:
+      enum    {ndims=3};
+      typedef fixed_vec<ndims,int> idx;
+      typedef fixed_vec<ndims,double> vect;
+      
+      double _start_t;
+      double _step_t;
+      
+      void allocate(int n,const idx& sz)
+      {
+        _volumes.resize(n);
+        for(int i=0;i<n;i++)
+        {
+          _volumes[i].resize(sz);
+        }
+      }
+      
+    public:
+      typedef simple_volume<T> volume;
+      typedef std::vector<volume> volume_list;
+      
+      int dim(int i) const
+      {
+        return _volumes[0].dim(i);
+      }
+      
+      vect voxel_to_world(const idx& iii) const
+      {
+        return _volumes[0].voxel_to_world(iii);
+      }
+      
+      idx world_to_voxel(const vect& iii) const
+      {
+        return _volumes[0].world_to_voxel(iii);
+      }
+      
+      void resize(int x,int y,int z,int t)
+      {
+        allocate(t,IDX<int>(x,y,z));
+      }
+      
+      //! number of temporal frames
+      size_t  frames(void) const
+      {
+        return _volumes.size();
+      }
+      
+      T& at(int x,int y,int z,int t)
+      {
+        return _volumes[t].at(x,y,z);
+      }
+      
+      const T& get(int x,int y,int z,int t) const
+      {
+        return _volumes[t].get(x,y,z);
+      }
+      
+      void set(int x,int y,int z,int t,const T& v)
+      {
+        _volumes[t].set(x,y,z,v);
+      }
+      
+      T& at(const idx& i,int t)
+      {
+        return _volumes[t].at(i);
+      }
+
+      const T& get(const idx& i,int t) const
+      {
+        return _volumes[t].get(i);
+      }
+      
+      void set(const idx& i,int t,const T& v)
+      {
+        _volumes[t].set(i,v);
+      }
+      
+      volume& frame(int t) 
+      {
+        return _volumes[t];
+      }
+
+      const volume& frame(int t) const
+      {
+        return _volumes[t];
+      }
+      
+      vect& start(void)
+      {
+        return _volumes[0].start();
+      }
+      
+      const vect& start(void) const
+      {
+        return _volumes[0].start();
+      }
+      
+      vect& step(void)
+      {
+        return _volumes[0].step();
+      }
+      
+      const vect& step(void) const
+      {
+        return _volumes[0].step();
+      }
+      
+      vect& direction_cosines(int i)
+      {
+        return _volumes[0].direction_cosines(i);
+      }
+      
+      const vect& direction_cosines(int i) const
+      {
+        return _volumes[0].direction_cosines(i);
+      }
+      
+      double & t_step(void)
+      {
+        return _step_t;
+      }
+      
+      double t_step(void) const
+      {
+        return _step_t;
+      }
+      
+      double & t_start(void)
+      {
+        return _start_t;
+      }
+      
+      double t_start(void) const
+      {
+        return _start_t;
+      }
+      
+    protected:
+
+      volume_list _volumes;
+  }; 
+
+};
+
+#endif //__MINC_IO_4D_VOLUME_H_
new file mode 100644
--- /dev/null
+++ b/ezminc/minc_io_exceptions.h
@@ -0,0 +1,58 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : 
+@DESCRIPTION: 
+@COPYRIGHT  :
+              Copyright 2006 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#ifndef __EXCPETIONS_H__
+#define __EXCPETIONS_H__
+
+#define REPORT_ERROR(MSG) throw minc::generic_error(__FILE__,__LINE__,MSG)
+
+namespace minc
+{
+  class generic_error
+  {
+  public:
+    const char *_file;
+    int _line;
+    const char *_msg;
+    int _code;
+  public:
+
+    generic_error (const char *file, int line, const char *msg = "Error", int code = 0):
+    _file (file), _line (line), _msg (msg), _code (code)
+    {
+      //                    std::cerr<<"Exception created: "<<_file<<":"<<_line<<" "<<_msg<<std::endl;
+    }
+
+    const char *file (void) const
+    {
+      return _file;
+    }
+
+    const char *msg (void) const
+    {
+      return _msg;
+    }
+
+    int line (void) const
+    {
+      return _line;
+    }
+
+    int code (void) const
+    {
+      return _code;
+    }
+  };
+}; //minc
+#endif //__EXCPETIONS_H__
new file mode 100644
--- /dev/null
+++ b/ezminc/minc_io_fixed_vector.h
@@ -0,0 +1,375 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : 
+@DESCRIPTION: 
+@COPYRIGHT  :
+              Copyright 2006 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#ifndef __FIXED_VECTOR_H__
+#define __FIXED_VECTOR_H__
+
+#include <limits>
+
+namespace minc
+{
+  //! fixed size array, which support arithmetic operations
+  template<int dim,class I=int> class fixed_vec
+  {
+  protected:
+    I c[dim];
+  public:
+    //! default constructor, does nothing (i.e data is uninitilized)
+    fixed_vec() {}
+  
+    //! constructor which sets all the elements to the same value
+    explicit fixed_vec(I v)
+    {
+        for(unsigned int i=0;i<dim;i++)
+            c[i]=v;
+    }
+
+    //! constructor which sets all the elements to be a copy of C-array
+    explicit fixed_vec(const I* v)
+    {
+        for(unsigned int i=0;i<dim;i++)
+            c[i]=v[i];
+    }
+    
+    //! conversion to the C array
+    I* c_buf()
+    {
+      return c;
+    }
+	
+    //! conversion to const C array 
+    const I* c_buf() const
+    {
+      return c;
+    }
+
+    //! element access operator
+    I& operator[](int i)
+    {
+#ifdef _INDEX_CHECK
+      if(i<0 || i>=dim) REPORT_ERROR("Index out of bounds");
+#endif //_INDEX_CHECK
+      return c[i];
+    }
+    //! const element access operator
+    I operator[](int i) const
+    {
+#ifdef _INDEX_CHECK
+      if(i<0 || i>=dim) REPORT_ERROR("Index out of bounds");
+#endif //_INDEX_CHECK
+      return c[i];
+    }
+
+    //! const element access operator
+    I get(int i)
+    {
+      return (*this)[i];
+    }
+    //! element writing operator
+    void set(int i,I v)
+    {
+      (*this)[i]=v;
+    }
+
+    //! find a maximum of elements
+    I max(void) const
+    {
+      I s=std::numeric_limits < I >::min ();;
+      for(unsigned int i=0;i<dim;i++)
+        if(c[i]>s) s=c[i];
+      return s;
+    }
+	
+    //! find a minimum of elements
+    I min(void) const
+    {
+      I s=std::numeric_limits < I >::max ();;
+      for(unsigned int i=0;i<dim;i++)
+        if(c[i]<s) s=c[i];
+      return s;
+    }
+	
+    //! calculate sum of all elements
+    I sum(void) const
+    {
+      I s=0;
+      for(unsigned int i=0;i<dim;i++)
+        s+=c[i];
+      return s;
+    }
+
+    //! modulus squared
+    I mod2(void) const
+    {
+      I s=0;
+      for(unsigned int i=0;i<dim;i++)
+        s+=c[i]*c[i];
+      return s;
+    }
+    
+    //! volume (product of all elements)
+    I vol(void) const
+    {
+      I s=1;
+      for(unsigned int i=0;i<dim;i++)
+        s*=c[i];
+      return s;
+    }
+	
+    //! \name fixed_vec arithmentic operations
+    //@{
+    fixed_vec<dim,I>& operator *=(const fixed_vec<dim,I>& b)
+    {
+      for(unsigned int i=0;i<dim;i++)
+        c[i]*=b[i];
+      return *this;
+    }
+
+    fixed_vec<dim,I>& operator *=(const I b)
+    {
+      for(unsigned int i=0;i<dim;i++)
+        c[i]*=b;
+      return *this;
+    }
+
+    fixed_vec<dim,I>& operator +=(const fixed_vec<dim,I>& b)
+    {
+      for(unsigned int i=0;i<dim;i++)
+        c[i]+=b[i];
+      return *this;
+    }
+
+    fixed_vec<dim,I>& operator -=(const fixed_vec<dim,I>& b)
+    {
+      for(unsigned int i=0;i<dim;i++)
+        c[i]-=b[i];
+      return *this;
+    }
+
+    fixed_vec<dim,I>& operator /=(const fixed_vec<dim,I>& b)
+    {
+      for(unsigned int i=0;i<dim;i++)
+        c[i]/=b[i];
+      return *this;
+    }
+
+    fixed_vec<dim,I>& operator /=(const I b)
+    {
+      for(unsigned int i=0;i<dim;i++)
+        c[i]/=b;
+      return *this;
+    }
+
+    fixed_vec<dim,I> operator /(const I b)
+    {
+      fixed_vec<dim,I> tmp;
+      for(unsigned int i=0;i<dim;i++)
+        tmp[i]=c[i]/b;
+      return tmp;
+    }
+
+    fixed_vec<dim,I> operator *(const I b)
+    {
+      fixed_vec<dim,I> tmp;
+      for(unsigned int i=0;i<dim;i++)
+        tmp[i]=c[i]*b;
+      return tmp;
+    }
+
+    fixed_vec<dim,I> operator -(const fixed_vec<dim,I>& b)
+    {
+      fixed_vec<dim,I> tmp;
+      for(unsigned int i=0;i<dim;i++)
+        tmp[i]=c[i]-b[i];
+      return tmp;
+    }
+
+    fixed_vec<dim,I> operator +(const fixed_vec<dim,I>& b)
+    {
+      fixed_vec<dim,I> tmp;
+      for(unsigned int i=0;i<dim;i++)
+        tmp[i]=c[i]+b[i];
+      return tmp;
+    }
+
+    //@}
+
+    //! assignement operator, copies contents
+    fixed_vec<dim,I>& operator=(const fixed_vec<dim,I>& b)
+    {
+      for(unsigned int i=0;i<dim;i++)
+        c[i]=b[i];
+      return *this;
+    }
+
+    //! assignement operator, copies contents, assumes that b have at least this size
+    fixed_vec<dim,I>& operator=(const I* b)
+    {
+      for(unsigned int i=0;i<dim;i++)
+        c[i]=b[i];
+      return *this;
+    }
+
+    //! assignement operator, sets all elements to the same value
+    fixed_vec<dim,I>& operator=(const I b)
+    {
+      for(unsigned int i=0;i<dim;i++) c[i]=b;
+      return *this;
+    }
+
+    //! inequality operator, does element wise equality check
+    bool operator!=(const fixed_vec<dim,I>& b) const
+    {
+      for(int i=0;i<dim;i++) if(c[i]!=b[i]) return true;
+      return false;
+    }
+	
+    //! equality operator, does element wise equality check
+    bool operator==(const fixed_vec<dim,I>& b) const
+    {
+      for(int i=0;i<dim;i++) if(c[i]!=b[i]) return false;
+      return true;
+    }
+    
+    //! reverse the order of elements
+    void reverse(void)
+    {
+      for(int i=0;i<dim/2;i++)
+      {
+        I tmp=c[i];
+        c[i]=c[dim-i-1];
+        c[dim-i-1]=tmp;
+      }
+    }
+  };
+
+  //! element wise division
+	template<int dim,class I> fixed_vec<dim,I> operator/(const fixed_vec<dim,I> &l,const fixed_vec<dim,I> &r)
+	{
+		fixed_vec<dim,I> out=l;
+		out/=r;
+		return out; //this is not effecient  - no return value optimisation
+	}
+  
+	//! element wise multiplication
+	template<int dim,class I> fixed_vec<dim,I> operator*(const fixed_vec<dim,I> &l,const fixed_vec<dim,I> &r)
+	{
+		fixed_vec<dim,I> out=l;
+		out*=r;
+		return out; //this is not effecient  - no return value optimisation
+	}
+  
+	//! element wise addition
+	template<int dim,class I> fixed_vec<dim,I> operator+(const fixed_vec<dim,I> &l,const fixed_vec<dim,I> &r)
+	{
+		fixed_vec<dim,I> out=l;
+		out+=r;
+		return out; //this is not effecient  - no return value optimisation
+	}
+	
+  //! element wise subtraction
+	template<int dim,class I> fixed_vec<dim,I> operator-(const fixed_vec<dim,I> &l,const fixed_vec<dim,I> &r)
+	{
+		fixed_vec<dim,I> out=l;
+		out-=r;
+		return out; //this is not effecient  - no return value optimisation
+	}
+	
+	//! devide all elements by a value
+	template<int dim,class I> fixed_vec<dim,I> operator/(const fixed_vec<dim,I> &l,I r)
+	{
+		fixed_vec<dim,I> out=l;
+		out/=r;
+		return out; //this is not effecient  - no return value optimisation
+	}
+	
+  //! multiply all elements by a value 
+	template<int dim,class I> fixed_vec<dim,I> operator*(const fixed_vec<dim,I> &l,I r)
+	{
+		fixed_vec<dim,I> out=l;
+		out*=r;
+		return out; //this is not effecient  - no return value optimisation
+	}
+	
+  //! add a value to all elements 
+	template<int dim,class I> fixed_vec<dim,I> operator+(const fixed_vec<dim,I> &l,I r)
+	{
+		fixed_vec<dim,I> out=l;
+		out+=r;
+		return out; //this is not effecient  - no return value optimisation
+	}
+	
+  //! subtract a value from all elements 
+	template<int dim,class I> fixed_vec<dim,I> operator-(const fixed_vec<dim,I> &l,I r)
+	{
+		fixed_vec<dim,I> out=l;
+		out-=r;
+		return out; //this is not effecient  - no return value optimisation
+	}
+	
+	//! create 1d fixed_vec
+	template<class I> fixed_vec<1,I> IDX(I i)
+	{
+		fixed_vec<1,I> d;
+		d[0]=i;
+		return d;
+	}
+	
+	//! create 2d fixed_vec
+	template<class I> fixed_vec<2,I> IDX(I i,I j)
+	{
+		fixed_vec<2,I> d;
+		d[0]=i;
+		d[1]=j;
+		return d;
+	}
+	
+	//! create 3d fixed_vec
+	template<class I> fixed_vec<3,I> IDX(I i,I j,I k)
+	{
+		fixed_vec<3,I> d;
+		d[0]=i;
+		d[1]=j;
+		d[2]=k;
+		return d;
+	}
+	
+	//! create 4d fixed_vec
+	template<class I> fixed_vec<4,I> IDX(I i,I j,I k,I l)
+	{
+		fixed_vec<3,I> d;
+		d[0]=i;
+		d[1]=j;
+		d[2]=k;
+		d[3]=l;
+		return d;
+	}
+	
+	//!average value of a vector
+	template<class T,int d>T AVG(const fixed_vec<d,T> &v)
+	{
+		return v.sum()/d;
+	}	
+  
+	//!dot product of two vectors
+  template<class T,int d>T dot(const fixed_vec<d,T> &v1,const fixed_vec<d,T> &v2)
+  {
+    T val=0;
+    for(int i=0;i<d;i++) val+=v1[i]*v2[i];
+    return val;
+  }	
+	
+};
+
+#endif //__FIXED_VECTOR_H__
new file mode 100644
--- /dev/null
+++ b/ezminc/minc_io_simple_volume.h
@@ -0,0 +1,554 @@
+#ifndef __SIMPLE_VOLUME_H__
+#define __SIMPLE_VOLUME_H__
+
+#include "minc_io_exceptions.h"
+#include "minc_io_fixed_vector.h"
+#include <string.h>
+#include <math.h>
+
+namespace minc 
+{
+  //! very simple 3D volume, initially created as an example but became usable
+    template<class T> class simple_volume
+    {
+    public:
+    
+      enum    {ndims=3};
+      typedef fixed_vec<ndims,int> idx;
+      typedef fixed_vec<ndims,double> vect;
+      
+    protected:
+    
+      T * _vol;    //! the volume itself
+      idx _size;   //! dimension sizes
+      idx _stride; //! used internally 
+      int _count;  //! total number of voxels
+      bool _free_memory; //! should the array be freed
+      
+      vect _step,_start;    //! conversion to wold coordinates
+      vect _direction_cosines[3];
+      
+      
+      void _allocate(T* data=NULL)
+      {
+        _stride[0]=1;
+        int total=_size[0];
+        for(int i=1;i<ndims;i++)
+        {
+          _stride[i]=_size[i-1]*_stride[i-1];
+          total*=_size[i];
+        }
+        _count=total;
+        if(data)
+        {
+          _vol=data;
+          _free_memory=false;
+        } else {
+          _vol=new T[total];
+          _free_memory=true;
+        }
+        
+        _step=IDX<double>(1.0,1.0,1.0);
+        _start=IDX<double>(0.0,0.0,0.0);
+        
+        _direction_cosines[0]=IDX<double>(1.0,0.0,0.0);
+        _direction_cosines[1]=IDX<double>(0.0,1.0,0.0);
+        _direction_cosines[2]=IDX<double>(0.0,0.0,1.0);
+        
+      }
+
+    public:
+      vect& start(void)
+      {
+        return _start;
+      }
+      
+      const vect& start(void) const
+      {
+        return _start;
+      }
+
+      vect& step(void)
+      {
+        return _step;
+      }
+      
+      
+      const vect& step(void) const
+      {
+        return _step;
+      }
+      
+      vect& direction_cosines(int i)
+      {
+        return _direction_cosines[i];
+      }
+      
+      const vect& direction_cosines(int i) const
+      {
+        return _direction_cosines[i];
+      }
+
+      operator T*() 
+      {
+        return _vol;
+      }
+      
+      T* c_buf() 
+      {
+        return _vol;
+      }
+      
+      const T* c_buf() const
+      {
+        return _vol;
+      }
+      
+      int c_buf_size() const
+      {
+        return _count;
+      }
+
+      explicit simple_volume(const int* dims):_vol(0),_size(dims)
+      {
+        _allocate();
+      }
+      
+      simple_volume(const simple_volume<T>& a,bool copy_data=true):_vol(0)
+      {
+        for(int i=0;i<ndims;i++) 
+          _size[i]=a._size[i];
+        _allocate();
+        
+        if(copy_data)
+        {
+          memmove(_vol,a._vol,_size[0]*_size[1]*_size[2]*sizeof(T));
+        }
+        
+        _step=a._step;
+        _start=a._start;
+        for(int i=0;i<ndims;i++)
+          _direction_cosines[i]=a._direction_cosines[i];
+      }
+      
+      simple_volume(int sx,int sy,int sz):_vol(0)
+      {
+        _size=IDX(sx,sy,sz);
+        _allocate();
+      }
+      
+      explicit simple_volume(const idx& s):_vol(0)
+      {
+        _size=s;
+        _allocate();
+      }
+
+      simple_volume():_vol(0)
+      {
+        for(int i=0;i<ndims;i++)
+        {
+          _size[i]=0;
+          _step[i]=0.0;
+          _start[i]=0.0;
+          
+          _direction_cosines[i]=IDX<double>(0.0,0.0,0.0);
+          _direction_cosines[i][i]=1.0;
+        }
+      }
+      
+      bool empty(void) const
+      {
+        return !_size[0]||!_vol;
+      }
+      
+      void resize(int sx,int sy,int sz)
+      {
+        if( _size[0]==sx && _size[1]==sy && _size[2]==sz )
+          return;
+        
+        if(_vol && _free_memory)
+          delete [] _vol;
+        _size=IDX(sx,sy,sz);
+        _allocate();
+      }
+      
+      void resize(const idx& s)
+      {
+        if(_size==s) return;
+        
+        if(_vol&&_free_memory)
+          delete [] _vol;
+        _size=s;
+        _allocate();
+      }
+      
+      virtual ~simple_volume()
+      {
+        if(_vol && _free_memory)
+          delete [] _vol;
+      }
+      
+      T& operator()(int x,int y,int z)
+      {
+        return _vol[x+y*_stride[1]+z*_stride[2]];
+      }
+      
+      T& operator()(const idx& i)
+      {
+        return _vol[dot(i,_stride)];
+      }
+      
+      const T& operator()(int x,int y,int z) const
+      {
+        return get(x,y,z);
+      }
+      
+      const T& operator()(const idx& i) const
+      {
+        return get(i);
+      }
+      
+      const T& get(int x,int y,int z) const
+      {
+        return _vol[x+y*_stride[1]+z*_stride[2]];
+      }
+      
+      const T& get(const idx& i) const
+      {
+        return _vol[dot(i,_stride)];
+      }
+      
+      const T& safe_get(int x,int y,int z) const
+      {
+        check_index(x,y,z);
+        return _vol[x+y*_stride[1]+z*_stride[2]];
+      }
+     
+      const T& safe_get(idx i) const
+      {
+        check_index(i);
+        return get(i);
+      }
+
+      //trilinear intrpolation
+      double interpolate(float _x,float _y,float _z) const
+      {
+        int x=floor(_x);
+        int y=floor(_y);
+        int z=floor(_z);
+        
+        float dx=_x-x;
+        float dy=_y-y;
+        float dz=_z-z;
+        
+        if(x<0) x=-x;
+        if(y<0) y=-y;
+        if(z<0) z=-z;
+        
+        if(x>=(_size[0]-1)) x=_size[0]*2-3-x;
+        if(y>=(_size[1]-1)) y=_size[1]*2-3-y;
+        if(z>=(_size[2]-1)) z=_size[2]*2-3-z;
+        
+        //trilinear intrpolation
+        return     (1.0-dx)*(1.0-dy)*(1.0-dz)*get(x,y,z)+
+        
+                   dx*(1.0-dy)*(1.0-dz)*get(x+1,y,z)+
+                   (1.0-dx)*dy*(1.0-dz)*get(x,y+1,z)+
+                   (1.0-dx)*(1.0-dy)*dz*get(x,y,z+1)+
+                   
+                   dx*(1.0-dy)*dz*get(x+1,y,z+1)+
+                   (1.0-dx)*dy*dz*get(x,y+1,z+1)+
+                   dx*dy*(1.0-dz)*get(x+1,y+1,z)+
+                   
+                   dx*dy*dz*get(x+1,y+1,z+1);
+      }
+      
+      T set(int x,int y,int z, const T&v)
+      {
+        return _vol[x+y*_stride[1]+z*_stride[2]]=v;
+      }
+      
+      T set(const idx& i, const T&v)
+      {
+        return _vol[dot(i,_stride)]=v;
+      }
+      
+      int dim(int i) const
+      {
+        return _size[i];
+      }
+      
+      const int* dims() const
+      {
+        return _size.c_buf();
+      }
+      
+      const idx& size() const
+      {
+        return _size;
+      }
+      
+      void extract_subvolume(simple_volume<T>& dst,const idx& s, const idx& f) const
+      {
+        for(int k=s[2];k<f[2];k++)
+         for(int j=s[1];j<f[1];j++)
+          for(int i=s[0];i<f[0];i++)
+            dst(i,j,k)=get(i,j,k);
+      }
+      
+      void check_index(int &ii,int &jj,int &kk) const
+      {
+        if(ii<0) ii=-ii;
+        if(jj<0) jj=-jj;
+        if(kk<0) kk=-kk;
+
+        if(ii>=dim(0)) ii=2*dim(0)-ii-1;
+        if(jj>=dim(1)) jj=2*dim(1)-jj-1;
+        if(kk>=dim(2)) kk=2*dim(2)-kk-1;
+      }
+      
+      void check_index(idx& iii)
+      {
+        for(int i=0;i<3;i++)
+        {
+          if(iii[i]<0) 
+            iii[i]=-iii[i];
+
+          if(iii[i]>=dim(i)) 
+            iii[i]=2*dim(i)-iii[i]-1;
+
+        }
+      }
+
+      bool hit(int ii,int jj,int kk) const
+      {
+        if(ii<0) return false;
+        if(jj<0) return false;
+        if(kk<0) return false;
+
+        if(ii>=dim(0)) return false;
+        if(jj>=dim(1)) return false;
+        if(kk>=dim(2)) return false;
+        return true;
+      }
+      
+      bool hit(const idx iii) const
+      {
+        for(int i=0;i<3;i++)
+        {
+          if(iii[i]<0) return false;
+          if(iii[i]>=dim(i)) return false;
+        }
+        return true;
+      }
+          
+      simple_volume<T>& operator+=(const simple_volume<T>& a)
+      {
+        for(int i=0;i<ndims;i++) 
+          if(_size[i]!=a._size[i])
+            REPORT_ERROR("Dimensions are different");
+        
+        for(int i=0;i<_count;i++)
+          _vol[i]+=a._vol[i];
+        return *this;
+      }
+      
+      simple_volume<T>& operator+=(const T& a)
+      {
+        for(int i=0;i<_count;i++)
+          _vol[i]+=a;
+        return *this;
+      }
+      
+      simple_volume<T>& operator-=(const simple_volume<T>& a)
+      {
+         if(_size!=a._size)
+            REPORT_ERROR("Dimensions are different");
+        
+        for(int i=0;i<_count;i++)
+          _vol[i]-=a._vol[i];
+        return *this;
+      }
+      
+      simple_volume<T>& operator-=(const T& a)
+      {
+        for(int i=0;i<_count;i++)
+          _vol[i]-=a;
+        return *this;
+      }
+      
+      simple_volume<T>& operator*=(const simple_volume<T>& a)
+      {
+        for(int i=0;i<ndims;i++) 
+          if(_size[i]!=a._size[i])
+            REPORT_ERROR("Dimensions are different");
+        
+        for(int i=0;i<_count;i++)
+          _vol[i]*=a._vol[i];
+        return *this;
+      }
+      
+      simple_volume<T>& operator*=(const T& a)
+      {
+        for(int i=0;i<_count;i++)
+          _vol[i]*=a;
+        return *this;
+      }
+      
+      simple_volume<T>& operator/=(const simple_volume<T>& a)
+      {
+        if(_size!=a._size())
+          REPORT_ERROR("Dimensions are different");
+        
+        for(int i=0;i<_count;i++)
+          _vol[i]/=a._vol[i];
+        return *this;
+      }
+      
+      simple_volume<T>& operator/=(const T& a)
+      {
+        for(int i=0;i<_count;i++)
+          _vol[i]/=a;
+        return *this;
+      }
+      
+      simple_volume& operator=(const simple_volume<T>&a)
+      {
+        resize(a.dim(0),a.dim(1),a.dim(2));
+        
+        memmove(_vol, a._vol, _count*sizeof(T));
+        
+        _step=a._step;
+        _start=a._start;
+        
+        for(int i=0;i<ndims;i++)
+          _direction_cosines[i]=a._direction_cosines[i];
+        
+        return *this;
+      }
+      
+      simple_volume& operator=(const T&a)
+      {
+        for(int i=0;i<_count;i++)
+          _vol[i]=a;
+        return *this;
+      }
+      
+      void weighted_add(const simple_volume<T>&a, double w)
+      {
+        if(_size!=a._size)
+          REPORT_ERROR("Dimensions are different");
+        
+        for(int i=0;i<_count;i++)
+          _vol[i]+=a._vol[i]*w;
+      }
+      
+      vect voxel_to_world(const idx& iii) const
+      {
+        vect ret=IDX<double>(0.0,0.0,0.0);
+        for(int i=0;i<ndims;i++)
+        {
+          for(int j=0;j<ndims;j++)
+            ret[i]+=(_step[j]*iii[j]+_start[j])*_direction_cosines[j][i];
+        }
+        return ret;
+      }
+
+      vect world_to_voxel_c(const vect& iii) const
+      {
+        vect ret=IDX<double>(0.0,0.0,0.0);
+        for(int i=0;i<ndims;i++)
+        {
+          for(int j=0;j<ndims;j++)
+            ret[i]+=((iii[j]-_start[j])/_step[j])*_direction_cosines[i][j]; //transpose!
+        }
+        return ret;
+      }
+
+      idx world_to_voxel(const vect& iii) const
+      {
+        vect ret=world_to_voxel_c(iii);
+        
+        idx r;
+        
+        for(int i=0;i<ndims;i++)
+          r[i]=floor(ret[i]+0.5);
+        
+        return r;
+      }
+      
+      //!use provided buffer for storage
+      void assign(const idx& s,T* array) 
+      {
+        _size=s;
+        allocate(array);
+      }
+      
+  };
+  
+  //! remove (unpad) or add padding as needed, volume will be centered
+  template<class T>void pad_volume(const simple_volume<T> &src,simple_volume<T> &dst, const T& fill)
+  {
+    fixed_vec<3,int> sz1=src.size();
+    fixed_vec<3,int> sz2=dst.size();
+    fixed_vec<3,int> d=sz2-sz1;
+    fixed_vec<3,int> i;
+    
+    d/=2;//offset
+  
+    for( i[2]=0;i[2]<sz2[2];i[2]++)
+      for( i[1]=0;i[1]<sz2[1];i[1]++)
+        for( i[0]=0;i[0]<sz2[0];i[0]++)
+    {
+      fixed_vec<3,int> j= i-d;
+      
+      if( src.hit(j)) 
+        dst.set(i,src.get(j));
+      else
+        dst.set(i,fill);
+    }
+  }
+  
+  template<class T>void volume_min_max(const simple_volume<T>& v,T &_min,T &_max)
+  {
+    _min=_max=v.c_buf()[0];
+    
+    for(int i=0;i<v.c_buf_size();i++)
+    {
+			if(isnan(v.c_buf()[i]) || isinf(v.c_buf()[i])) 
+				continue;
+			
+      if(v.c_buf()[i]>_max) _max=v.c_buf()[i];
+      else if(v.c_buf()[i]<_min) _min=v.c_buf()[i];
+    }
+  }
+  
+  template<class T> void  volume_min_max(const simple_volume<T>& v,const simple_volume<unsigned char>& mask,T &_min,T &_max)
+  {
+    if(v.size()!=mask.size())
+      REPORT_ERROR("Volume size mismatch");
+    
+    _min=1e10;
+    _max=-1e10;
+    
+    for(int i=0;i<v.c_buf_size();i++)
+    {
+      if(mask.c_buf()[i])
+      {
+				if(isnan(v.c_buf()[i]) || isinf(v.c_buf()[i])) 
+					continue;
+        if(v.c_buf()[i]>_max) _max=v.c_buf()[i];
+        else if(v.c_buf()[i]<_min) _min=v.c_buf()[i];
+      }
+    }
+  }
+  
+  
+  typedef simple_volume<float>               minc_float_volume;
+  typedef simple_volume<fixed_vec<3,float> > minc_grid_volume;
+  typedef simple_volume<unsigned char>       minc_byte_volume;
+
+}; //minc
+
+
+#endif // __SIMPLE_VOLUME_H__
new file mode 100644
--- /dev/null
+++ b/ezminc/tests/minc_com.cpp
@@ -0,0 +1,48 @@
+#include "minc_1_rw.h"
+#include <iostream>
+#include "minc_1_simple.h"
+#include "minc_1_simple_rw.h"
+
+using namespace minc;
+
+int main(int argc,char **argv)
+{
+  try
+  {
+    if(argc<2) {
+      std::cerr<<"Usage: "<<argv[0]<<" <input.mnc> "<<std::endl;
+      return 1;
+    }
+    minc_1_reader rdr;
+    rdr.open(argv[1],true);
+    simple_volume<float> vol;
+    load_simple_volume<float>(rdr,vol);
+    //calculate COM
+    fixed_vec<3,int> i;
+    fixed_vec<3,double> w;
+    double total=0;
+    double tx=0.0,ty=0.0,tz=0.0;
+    
+    for(i[2]=0;i[2]<vol.dim(2);i[2]++)
+      for(i[1]=0;i[1]<vol.dim(1);i[1]++)
+        for(i[0]=0;i[0]<vol.dim(0);i[0]++)
+        {
+          w=vol.voxel_to_world(i);
+          tx+=w[0]*vol.get(i);
+          ty+=w[1]*vol.get(i);
+          tz+=w[2]*vol.get(i);
+          total+=vol.get(i);
+        }
+    tx/=total;
+    ty/=total;
+    tz/=total;
+    std::cout<<tx<<","<<ty<<","<<tz<<std::endl;
+  } catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  
+  return 0;
+}
+
new file mode 100644
--- /dev/null
+++ b/ezminc/tests/minc_com_4d.cpp
@@ -0,0 +1,70 @@
+#include "minc_1_rw.h"
+#include <iostream>
+#include "minc_1_simple_rw.h"
+
+using namespace minc;
+
+int main(int argc,char **argv)
+{
+  try
+  {
+    if(argc<2) {
+      std::cerr<<"Usage: "<<argv[0]<<" <input.mnc> "<<std::endl;
+      return 1;
+    }
+    minc_1_reader rdr;
+    rdr.open(argv[1],true);
+    simple_4d_volume<float> vol;
+    load_4d_volume<float>(rdr,vol);
+    //calculate COM
+    fixed_vec<3,int> i;
+    fixed_vec<3,double> w;
+    
+    double total=0.0;
+    double tx=0.0,ty=0.0,tz=0.0,tT=0.0;
+    
+    //std::cout<<"T-start:"<<vol.t_start()<<std::endl;
+    //std::cout<<"T-step:"<<vol.t_step()<<std::endl;
+    
+    for(int t=0;t<vol.frames();t++)
+    {
+      double rt=t*vol.t_step()+vol.t_start();
+      
+      for(i[2]=0;i[2]<vol.dim(2);i[2]++)
+        for(i[1]=0;i[1]<vol.dim(1);i[1]++)
+          for(i[0]=0;i[0]<vol.dim(0);i[0]++)
+      {
+        w=vol.voxel_to_world(i);
+        
+        double v=vol.get(i,t);
+        
+        tx+=w[0]*v;
+        ty+=w[1]*v;
+        tz+=w[2]*v;
+        tT+=rt  *v;
+        
+        total+=v;
+        //std::cout<<v<<"\t";
+      }
+      //std::cout<<std::endl;
+      //std::cout<<rt<<"\t"<<tT<<"\t"<<std::flush;
+      std::cout<<"."<<std::flush;
+    }
+    std::cout<<std::endl;
+    
+    tx/=total;
+    ty/=total;
+    tz/=total;
+    tT/=total;
+    
+    std::cout<<tx<<","<<ty<<","<<tz<<","<<tT<<std::endl;
+    
+  } catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  
+  return 0;
+}
+
new file mode 100644
--- /dev/null
+++ b/ezminc/tests/minc_rw_test.cpp
@@ -0,0 +1,129 @@
+#include "minc_1_rw.h"
+#include <iostream>
+#include "minc_1_simple.h"
+
+using namespace minc;
+
+template<class T>class volume_3d
+{
+  protected:
+    T* _data;
+    int _x,_y,_z;
+  public:
+    
+    volume_3d(T* data,int x,int y,int z):_data(data),_x(x),_y(y),_z(z)
+    {
+    }
+    
+    volume_3d(std::vector<T> data,int x,int y,int z):_data(&data[0]),_x(x),_y(y),_z(z)
+    {
+    }
+    
+    T& operator()(int x,int y,int z)
+    {
+      return _data[x+y*_x+z*_x*_y];
+    }
+  
+};
+
+int main(int argc,char **argv)
+{
+  try
+  {
+    if(argc<4) {
+      std::cerr<<"Usage: "<<argv[0]<<" <input.mnc> <output.mnc> <output2.mnc>"<<std::endl;
+      return 1;
+    }
+    minc_1_reader rdr;
+    rdr.open(argv[1]);
+    int i;
+    for(i=0;i<rdr.dim_no();i++)
+      std::cout<<rdr.dim(i).name<<" "<<rdr.dim(i).length<<std::endl;
+    std::cout<<"Slice len="<<rdr.slice_len()<<std::endl;
+    std::cout<<"History:"<<rdr.history().c_str()<<std::endl;
+    for(int v=0;v<rdr.var_number();v++)
+    {
+      std::string var=rdr.var_name(v);
+      for(int a=0;a<rdr.att_number(v);a++)
+      {
+        std::string aname=rdr.att_name(v,a);
+        nc_type dt=rdr.att_type(v,aname.c_str());
+        
+        std::cout<<var.c_str()<<":"<<aname.c_str()<<" ";
+        if(dt==NC_CHAR) 
+          std::cout<<rdr.att_value_string(v,aname.c_str());
+        else if(dt=NC_DOUBLE) 
+        {
+          std::vector<double> val=rdr.att_value_double(v,aname.c_str());
+          for(int d=0;d<val.size();d++)
+            std::cout<<val[d]<<"\t";
+        } else {
+          std::cout<<"???";
+        }
+        std::cout<<std::endl;
+      }
+    }
+    
+    rdr.setup_read_float();
+    
+    minc_1_writer wrt;
+    wrt.open(argv[2],rdr.info(),2,NC_FLOAT,true);
+    wrt.setup_write_float();
+    std::vector<float> v(rdr.slice_len());
+
+    int c=0;
+    double s=0;
+    for(rdr.begin(),wrt.begin();!rdr.last();rdr.next_slice(),wrt.next_slice())
+    {
+      //std::cout<<wrt.current_slice()[0]<<std::endl;
+      rdr.read(&v[0]);
+      for(int i=0;i<rdr.slice_len();i++)
+      {
+        s+=v[i];
+        c++;
+      }
+      wrt.write(&v[0]);
+    }
+    s/=c;
+    //std::cout<<wrt._image_range[0]<<" "<<wrt._image_range[1]<<std::endl;
+    std::cout<<s<<std::endl;
+    wrt.copy_headers(rdr);
+    wrt.append_history("minc_rw_test test1\n");
+    
+    //second test
+    unsigned long size=1;
+    for(i=0;i<rdr.dim_no();i++)
+      size*=rdr.dim(i).length;
+    
+    minc_1_writer wrt2;
+    wrt2.open(argv[3],rdr.info(),3,NC_SHORT,false);
+    wrt2.setup_write_float();
+    
+    std::vector<float> buffer(size);
+    load_standard_volume<float>(rdr,&buffer[0]);
+    double avg2=0;
+    //for(int i=0;i<size;i++)
+    //  avg2+=buffer[i];
+    volume_3d<float> volume(buffer,rdr.ndim(dim_info::DIM_X),rdr.ndim(dim_info::DIM_Y),rdr.ndim(dim_info::DIM_Z));
+    for(int z=0;z<rdr.ndim(dim_info::DIM_Z);z++)
+      for(int y=0;y<rdr.ndim(dim_info::DIM_Y);y++)
+        for(int x=0;x<rdr.ndim(dim_info::DIM_X);x++)
+        {
+          avg2+=volume(x,y,z);
+        }
+    
+    avg2/=size;
+    std::cout<<"avg2 "<<avg2<<std::endl;
+    
+    save_standard_volume<float>(wrt2,&buffer[0]);
+    wrt2.copy_headers(rdr);
+    wrt2.append_history("minc_rw_test test2\n");
+  } catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  
+  return 0;
+}
+
new file mode 100644
--- /dev/null
+++ b/ezminc/tests/minc_rw_test2.cpp
@@ -0,0 +1,42 @@
+#include "minc_1_rw.h"
+#include <iostream>
+#include "minc_1_simple.h"
+#include "minc_io_simple_volume.h"
+
+using namespace minc;
+
+int main(int argc,char **argv)
+{
+  try
+  {
+    if(argc<3) {
+      std::cerr<<"Usage: "<<argv[0]<<" <input.mnc> <output.mnc>"<<std::endl;
+      return 1;
+    }
+    minc_1_reader rdr;
+    rdr.open(argv[1],true);
+    rdr.setup_read_float();
+    simple_volume<float> vol;
+    vol.resize(rdr.ndim(1),rdr.ndim(2),rdr.ndim(3));
+    load_non_standard_volume<float>(rdr,vol.c_buf());
+    //rdr.close();
+    for(int z=0;z<vol.dim(2);z++)
+      for(int y=0;y<vol.dim(1);y++)
+        for(int x=0;x<vol.dim(0);x++)
+        {
+          vol(x,y,z)=x;
+        }
+    minc_1_writer wrt;
+    wrt.open(argv[2],rdr.info(),3,NC_FLOAT,false);
+    wrt.setup_write_float();
+    save_non_standard_volume<float>(wrt,vol.c_buf());
+    
+  } catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  
+  return 0;
+}
+
new file mode 100644
--- /dev/null
+++ b/ezminc/tests/minc_rw_test_4d.cpp
@@ -0,0 +1,51 @@
+#include "minc_1_simple_rw.h"
+#include <iostream>
+
+using namespace minc;
+
+int main(int argc,char **argv)
+{
+  try
+  {
+    if(argc<3) {
+      std::cerr<<"Usage: "<<argv[0]<<" <input.mnc> <output.mnc>"<<std::endl;
+      return 1;
+    }
+    minc_1_reader rdr;
+    rdr.open(argv[1]);
+    
+    if(rdr.dim_no()==3|| (rdr.dim_no()==4 && rdr.ndim(4)>0 ))
+    {
+      if(rdr.datatype()==NC_FLOAT || rdr.datatype()==NC_SHORT)
+      {
+        std::cout<<"Reading float volume"<<std::endl;
+        simple_4d_volume<float> vol;
+        
+        load_4d_volume(rdr,vol);
+        save_minc_file(argv[2],vol,"test",&rdr,rdr.datatype(),rdr.is_signed());
+      } else if(rdr.datatype()==NC_BYTE) {
+        std::cout<<"Reading byte volume"<<std::endl;
+        simple_4d_volume<unsigned char> vol;
+        
+        load_4d_volume(rdr,vol);
+        save_minc_file(argv[2],vol,"test",&rdr,rdr.datatype(),rdr.is_signed());
+      }
+    } else if((rdr.dim_no()==4|| rdr.dim_no()==5)&&rdr.ndim(0)==3) { //we are dealing with vectors
+        std::cout<<"Reading vector volume"<<std::endl;
+        simple_4d_volume< fixed_vec<3,float> > vol;
+        
+        load_4d_volume(rdr,vol);
+        save_minc_file(argv[2],vol,"test",&rdr,rdr.datatype(),rdr.is_signed());
+    }
+    
+  } catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  
+  return 0;
+}
+
+
+
new file mode 100644
--- /dev/null
+++ b/ezminc/tests/minc_rw_test_simple.cpp
@@ -0,0 +1,43 @@
+#include "minc_1_rw.h"
+#include <iostream>
+#include "minc_1_simple.h"
+
+using namespace minc;
+
+int main(int argc,char **argv)
+{
+  try
+  {
+    if(argc<3) {
+      std::cerr<<"Usage: "<<argv[0]<<" <input.mnc> <output.mnc>"<<std::endl;
+      return 1;
+    }
+    minc_1_reader rdr;
+    rdr.open(argv[1],true);
+    rdr.setup_read_float();
+    
+    minc_1_writer wrt;
+    for(int i=0;i<3;i++)
+    {
+      std::cout<<rdr.info()[i].step<<" "<<rdr.info()[i].start<<std::endl;
+    }
+    wrt.open(argv[2],rdr.info(),3,NC_FLOAT,false);
+    wrt.setup_write_float();
+    minc_input_iterator<float> in(rdr);
+    minc_output_iterator<float> out(wrt);
+    float c=0.0;
+    for(in.begin(),out.begin();!in.last();in.next(),out.next())
+    {
+      out.value(in.value()+c);
+      c++;
+    }
+    
+	} catch (const minc::generic_error & err) {
+    std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
+    std::cerr << err.msg()<<std::endl;
+    return 1;
+  }
+  
+  return 0;
+}
+
new file mode 100644
--- /dev/null
+++ b/ezminc/tests/transformpoint.cpp
@@ -0,0 +1,29 @@
+#include <volume_io.h>
+#include <iostream>
+
+
+int main(int argc, char **argv)
+{
+  if(argc<5)
+  {
+    std::cerr<<"Usage:"<<argv[0]<<"<XFM file> X Y Z"<<std::endl;
+    return 1;
+  }
+  double x,y,z;
+  double _x,_y,_z;
+  
+  x=atof(argv[2]);
+  y=atof(argv[3]);
+  z=atof(argv[4]);
+  
+  General_transform _xfm;
+  if(input_transform_file((char*)argv[1], &_xfm)!=OK)
+  {
+    std::cerr<<"Error reading:"<<argv[1]<<std::endl;
+    return 1;
+  }
+  general_transform_point( &_xfm, x, y, z,&_x, &_y, &_z);  
+  delete_general_transform(&_xfm);
+  std::cout<<_x<<" "<<_y<<" "<<_z<<std::endl;
+  return 0;
+};
\ No newline at end of file
--- a/libsrc/netcdf_convenience.c
+++ b/libsrc/netcdf_convenience.c
@@ -229,7 +229,7 @@
 @INPUT      : command - command to execute
               infile - input file
               outfile - output file
-              header_only - TRUE if only header of minc file is needed
+              header_only - ignored
 @OUTPUT     : (none)
 @RETURNS    : status of decompress command (zero = success)
 @DESCRIPTION: Routine to execute a decompression command on a minc file.
@@ -244,18 +244,9 @@
 PRIVATE int execute_decompress_command(char *command, char *infile, 
                                        char *outfile, int header_only)
 {
-   int oldncopts;
    char whole_command[1024];
    int status;
-   FILE *pipe, *output;
-   char buffer[1024];
-   int successful_ncopen;
-   int ibuf;
-   int nread;
-   int processid;
 
-#define BYTES_PER_OPEN (1024*64)
-#define NUM_BUFFERS_PER_OPEN ((BYTES_PER_OPEN - 1) / sizeof(buffer) + 1)
 
 #if !(HAVE_WORKING_FORK && HAVE_SYSTEM && HAVE_POPEN)
 
@@ -263,105 +254,12 @@
 
 #else      /* Unix */
 
-
-   if (!header_only) {        /* Decompress the whole file */
-
-      (void) sprintf(whole_command, "exec %s %s > %s 2> /dev/null", 
-                     command, infile, outfile);
-      status = system(whole_command);
-   }
-   else {                     /* We just need to decompress enough for
-                                 the header */
-
-      /* Set up the command and open the pipe (we defer opening the output
-         file until we have read something) */
-      (void) sprintf(whole_command, "exec %s %s 2> /dev/null", 
-                     command, infile);
-      pipe = popen(whole_command, "r");
-      output = NULL;
-
-      /* Loop until we have successfully opened the minc file (the header
-         is all there) */
-      successful_ncopen = FALSE;
-      while (!successful_ncopen && !feof(pipe)) {
-
-         /* Loop, copying buffers from pipe to file. If the file hasn't been
-            opened, then open it */
-         for (ibuf=0; (ibuf < NUM_BUFFERS_PER_OPEN) && 
-              ((nread = 
-                fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0); 
-              ibuf++) {
-            if (output == NULL) {
-               output = fopen(outfile, "w");
-               if (output == NULL) {
-                  (void) fclose(pipe);
-                  return 1;
-               }
-            }
-            if (fwrite(buffer, sizeof(char), nread, output) != nread) {
-               (void) fclose(output);
-               (void) fclose(pipe);
-               return 1;
-            }
-         }      /* End of for loop, copying from pipe to output */
-         if (fflush(output)) {
-            (void) fclose(output);
-            (void) fclose(pipe);
-            return 1;
-         }
-
-#if MINC2
-	 successful_ncopen = hdf_access(outfile);
-	 if (successful_ncopen) {
-             break;
-         }
-#endif /* MINC2 */
-
-         /* Try to open minc file. There seems to be a bug in NetCDF 2.3.2 -
-            when the header is not all present in the file, we get a core
-            dump if ncopts does not have NC_FATAL set. There error is
-            reported to be in NC_free_var (var.c:54), called from 
-            NC_free_array (array.c:348). This is all called from 
-            NC_new_cdf (cdf.c:84), in NC_free_cdf, just after the error
-            return from xdr_cdf. The work-around is to fork, set fatal
-            and check the return status of the child. */
-         oldncopts = ncopts; ncopts = 0;
-         processid = fork();
-         if (!processid) {           /* Child */
-
-            /* Close all filehandles to avoid buffer flushing problems */
-            {
-               int f;
-               f=getdtablesize()-1; /* could use OPEN_MAX-1 instead */
-               if (f < 2) f = 2;    /* At least close 0,1,2 */
-               for (; f >= 0; f--) {
-                  (void) close(f);
-               }
-            }
-
-            /* Try the open */
-            ncopts = NC_FATAL;
-            status = ncopen(outfile, NC_NOWRITE);
-            (void) ncclose(status);
-            exit(0);
-
-         }
-
-         /* Parent gets status from child */
-         (void) waitpid(processid, &status, 0);
-         if (status == 0) {
-            successful_ncopen = TRUE;
-         }
-         ncopts = oldncopts;
-
-      }       /* End of while, waiting for successful ncopen */
-
-      (void) fclose(output);
-      (void) fclose(pipe);
-
-      status = !successful_ncopen;
-
-   }          /* End of if !header_only else */
+   /* we now ignore header_only and always uncompress the whole
+    * file as the previous "header only" hack that used to work
+    * on MINC1 files doesn't work reliably with MINC2 */
+   (void) sprintf(whole_command, "exec %s %s > %s 2> /dev/null", 
+                  command, infile, outfile);
+   status = system(whole_command);
 
    /* Return the status */
    return status;
new file mode 100644
--- /dev/null
+++ b/minc4itk/CMakeLists.txt
@@ -0,0 +1,57 @@
+FIND_PACKAGE(ITK REQUIRED)
+
+IF(NOT ITK_LIBRARIES)
+  MESSAGE( FATAL_ERROR "ITK libraries are not found!")
+ENDIF(NOT ITK_LIBRARIES)
+
+IF(NOT ITK_INCLUDE_DIRS)
+  MESSAGE( FATAL_ERROR "ITK include directories are not found!")
+ENDIF(NOT ITK_INCLUDE_DIRS	)
+
+#OPTION(BUILD_ITK_PLUGIN    "Build ITK plugin" OFF)
+OPTION(BUILD_MINC4ITK_EXAMPLES   "Build minc4itk examples" ON)
+
+LINK_DIRECTORIES(${ITK_LIBRARY_DIRS})
+
+INCLUDE_DIRECTORIES(
+	${ITK_INCLUDE_DIRS}
+	)
+    
+SET( MINC4ITK_HEADERS
+    itkMincImageIOFactory.h
+    minc_general_transform.h
+    minc_helpers.h
+    itkMincImageIO.h
+    )
+
+SET( MINC4ITK_SRC 
+    minc_helpers.cxx
+    itkMincImageIO.cxx
+    itkMincImageIOFactory.cxx
+  )
+
+ADD_LIBRARY( minc4itk ${MINC4ITK_HEADERS} ${MINC4ITK_SRC})
+
+TARGET_LINK_LIBRARIES( minc4itk 
+    minc_io
+    ${ITK_LIBRARIES}
+    itkvnl_algo 
+    itkvnl 
+    ${minc_LIB}
+    ${volume_io_LIB}
+    m 
+    z )
+
+#VF ITK plugin is disabled for now
+#IF(BUILD_ITK_PLUGIN)
+#ADD_LIBRARY( minc4itk_plugin SHARED minc4itk_plugin.cxx)
+#TARGET_LINK_LIBRARIES(  minc4itk_plugin minc4itk)
+#INSTALL(TARGETS minc4itk_plugin LIBRARY DESTINATION lib)
+#ENDIF(BUILD_ITK_PLUGIN)
+
+INSTALL(TARGETS minc4itk ARCHIVE DESTINATION lib)
+INSTALL(FILES  ${MINC4ITK_HEADERS} DESTINATION include)
+
+IF(BUILD_MINC4ITK_EXAMPLES)
+add_subdirectory(examples)
+ENDIF(BUILD_MINC4ITK_EXAMPLES)
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/minc4itk/examples/CMakeLists.txt
@@ -0,0 +1,17 @@
+LINK_LIBRARIES( minc4itk )
+
+
+
+
+ADD_EXECUTABLE(itk_convert itk_convert.cpp)
+ADD_EXECUTABLE(itk_distance itk_distance.cpp)
+ADD_EXECUTABLE(itk_dti itk_dti.cpp)
+ADD_EXECUTABLE(itk_resample itk_resample.cpp)
+ADD_EXECUTABLE(volume_2_csv volume_2_csv.cpp)
+
+
+INSTALL(TARGETS
+  itk_convert
+  itk_distance
+  itk_resample
+   DESTINATION bin)
new file mode 100644
--- /dev/null
+++ b/minc4itk/examples/itk_convert.cpp
@@ -0,0 +1,287 @@
+#include <iostream>
+
+#include <itkImage.h>
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+#include <itkImageIOFactory.h>
+#include <itkImageIOBase.h>
+#include <itkFlipImageFilter.h>
+
+#include "itkMincImageIOFactory.h"
+#include "itkMincImageIO.h"
+
+#include <getopt.h>
+
+void show_usage (const char *name)
+{
+  std::cerr 
+      << "Usage: "<<name<<" <input> <output> " << std::endl
+      << "--clobber clobber output files"<<std::endl
+      << "--verbose be verbose"<<std::endl
+      << "--inv-x invert X axis"<<std::endl
+      << "--inv-y invert Y axis"<<std::endl
+      << "--inv-z invert Z axis"<<std::endl
+      << "--center set origin to the center of the image"<<std::endl
+;
+}
+typedef itk::ImageIOBase IOBase;
+typedef itk::SmartPointer<IOBase> IOBasePointer;
+
+template<class ImageType> void load_and_save_image(IOBase* base,
+                    const char *fname,
+                    bool inv_x=false,
+                    bool inv_y=false,
+                    bool inv_z=false,
+                    bool center=false,
+                    bool verbose=false)
+{
+  typename itk::ImageFileReader<ImageType >::Pointer reader = itk::ImageFileReader<ImageType >::New();
+  typename itk::FlipImageFilter<ImageType >::Pointer flip=itk::FlipImageFilter<ImageType >::New();
+  reader->SetImageIO(base);
+  reader->SetFileName(base->GetFileName());
+  reader->Update();
+  
+  typename ImageType::Pointer img=reader->GetOutput();
+     
+  /* WRITING */
+  if(verbose)
+    std::cout<<"Writing "<<fname<<"..."<<std::endl;
+  
+
+  
+  if(inv_x||inv_y||inv_z)
+  {
+    typename itk::FlipImageFilter<ImageType >::FlipAxesArrayType arr;
+    arr[0]=inv_x;
+    arr[1]=inv_y;
+    arr[2]=inv_z;
+    flip->SetFlipAxes(arr);
+    flip->SetInput(img);
+    flip->Update();
+    img=flip->GetOutput();
+  }
+  
+  if(center)//move origin to the center of the image
+  {
+    typename ImageType::RegionType r=img->GetLargestPossibleRegion();
+    std::vector<double> corner[3];
+    
+    typename ImageType::IndexType idx;
+    typename ImageType::PointType c;
+    
+    idx[0]=r.GetIndex()[0]+r.GetSize()[0]/2.0;
+    idx[1]=r.GetIndex()[1]+r.GetSize()[1]/2.0;
+    idx[2]=r.GetIndex()[2]+r.GetSize()[2]/2.0;
+    
+    img->TransformIndexToPhysicalPoint(idx,c);
+    
+    typename ImageType::PointType org=img->GetOrigin();
+    
+    org[0]-=c[0];
+    org[1]-=c[1];
+    org[2]-=c[2];
+    
+    img->SetOrigin(org);
+  }  
+  
+  typename itk::ImageFileWriter< ImageType >::Pointer writer = itk::ImageFileWriter<ImageType >::New();
+  writer->SetFileName(fname);
+  writer->SetInput( img );
+  writer->Update();
+  
+}
+
+int main(int argc,char **argv)
+{
+  int verbose=0;
+  int clobber=0;
+  int inv_x=0,inv_y=0,inv_z=0,center=0;
+  //char *history = time_stamp(argc, argv); //maybe we should free it afterwards
+
+  static struct option long_options[] = { 
+    {"verbose", no_argument, &verbose, 1},
+    {"quiet", no_argument, &verbose, 0},
+    {"clobber", no_argument, &clobber, 1},
+    {"inv-x", no_argument,  &inv_x, 1},
+    {"inv-y", no_argument,  &inv_y, 1},
+    {"inv-z", no_argument,  &inv_z, 1},
+    {"center", no_argument, &center, 1},
+    {0, 0, 0, 0}
+  };
+    
+  int c;
+  for (;;)
+  {
+    /* getopt_long stores the option index here. */
+    int option_index = 0;
+
+    c = getopt_long (argc, argv, "", long_options, &option_index);
+
+    /* Detect the end of the options. */
+    if (c == -1)
+      break;
+
+    switch (c)
+    {
+      case 0:
+        break;
+      case '?':
+        /* getopt_long already printed an error message. */
+      default:
+        show_usage (argv[0]);
+        return 1;
+    }
+  }
+  
+  if((argc - optind)<2)
+  {
+    show_usage(argv[0]);
+    return 1;
+  }
+  std::string input=argv[optind];
+  std::string output=argv[optind+1];
+  
+  if (!clobber && !access (output.c_str(), F_OK))
+  {
+    std::cerr << output.c_str () << " Exists!" << std::endl;
+    return 1;
+  }
+ 
+  try
+  {
+    //registering the MINC_IO factory
+    itk::ObjectFactoryBase::RegisterFactory(itk::MincImageIOFactory::New());
+    /* READING */
+    if(verbose) 
+      std::cout<<"Reading "<<input.c_str()<<"..."<<std::endl;
+    
+    //try to figure out what we have got
+    IOBasePointer io = itk::ImageIOFactory::CreateImageIO(input.c_str(), itk::ImageIOFactory::ReadMode );
+    
+    if(!io)
+      throw itk::ExceptionObject("Unsupported image file type");
+    
+    io->SetFileName(input.c_str());
+    io->ReadImageInformation();
+
+    size_t nd = io->GetNumberOfDimensions();
+    size_t nc = io->GetNumberOfComponents();
+    itk::ImageIOBase::IOComponentType  ct = io->GetComponentType();
+    std::string ct_s = io->GetComponentTypeAsString(ct);
+    
+    if(verbose)
+    {
+      std::cout<<"dimensions:"<<nd<<std::endl
+          <<"components:"<<nc<<std::endl
+          <<"type:"<<ct_s.c_str()<<std::endl;
+    }
+    
+    if(nd==3 && nc==1)
+    {
+      if(verbose) std::cout<<"Writing 3D image..."<<std::endl;
+        switch(ct)
+        {
+          case itk::ImageIOBase::UCHAR :
+            load_and_save_image<itk::Image<unsigned char, 3> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::CHAR :
+            load_and_save_image<itk::Image<char, 3> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::USHORT :
+            load_and_save_image<itk::Image<unsigned short, 3> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::SHORT :
+            load_and_save_image<itk::Image<short, 3> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::INT :
+            load_and_save_image<itk::Image<int, 3> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          case itk::ImageIOBase::UINT:
+            load_and_save_image<itk::Image<unsigned int, 3> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          case itk::ImageIOBase::FLOAT :
+            load_and_save_image<itk::Image<float, 3> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          case itk::ImageIOBase::DOUBLE:
+            load_and_save_image<itk::Image<double, 3> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          default:
+            itk::ExceptionObject("Unsupported component type");
+        }
+    } else if((nd==4 && nc==1)) {
+      if(verbose) std::cout<<"Writing 4D image..."<<std::endl;
+        switch(ct)
+        {
+          case itk::ImageIOBase::UCHAR:
+            load_and_save_image<itk::Image<unsigned char, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::CHAR:
+            load_and_save_image<itk::Image<char, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::USHORT:
+            load_and_save_image<itk::Image<unsigned short, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::SHORT:
+            load_and_save_image<itk::Image<short, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::INT:
+            load_and_save_image<itk::Image<int, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          case itk::ImageIOBase::UINT:
+            load_and_save_image<itk::Image<unsigned int, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          case itk::ImageIOBase::FLOAT:
+            load_and_save_image<itk::Image<float, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          case itk::ImageIOBase::DOUBLE:
+            load_and_save_image<itk::Image<double, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          default:
+            itk::ExceptionObject("Unsupported component type");
+        }
+    } else if((nd==3 && nc>1)) {
+        if(verbose) std::cout<<"Writing multicomponent 3D image..."<<std::endl;
+
+        switch(ct)
+        {
+          case itk::ImageIOBase::UCHAR:
+            load_and_save_image<itk::VectorImage<unsigned char, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::CHAR:
+            load_and_save_image<itk::VectorImage<char, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::USHORT:
+            load_and_save_image<itk::VectorImage<unsigned short, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::SHORT:
+            load_and_save_image<itk::VectorImage<short, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break;
+          case itk::ImageIOBase::INT:
+            load_and_save_image<itk::VectorImage<int, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          case itk::ImageIOBase::UINT:
+            load_and_save_image<itk::VectorImage<unsigned int, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          case itk::ImageIOBase::FLOAT:
+            load_and_save_image<itk::VectorImage<float, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          case itk::ImageIOBase::DOUBLE:
+            load_and_save_image<itk::VectorImage<double, 4> >(io,output.c_str(),inv_x,inv_y,inv_z,center,verbose);
+            break; 
+          default:
+            itk::ExceptionObject("Unsupported component type");
+        }
+    } else {
+        throw itk::ExceptionObject("Unsupported number of dimensions");
+    }
+    
+  }
+  
+  catch( itk::ExceptionObject & err )
+  {
+    std::cerr << "ExceptionObject caught !" << std::endl;
+    std::cerr << err << std::endl;
+    return 2;
+  }
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/minc4itk/examples/itk_distance.cpp
@@ -0,0 +1,139 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : 
+@DESCRIPTION: 
+@COPYRIGHT  :
+              Copyright 2006 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include <unistd.h>
+#include <getopt.h>
+#include <iostream>
+#include <itkDanielssonDistanceMapImageFilter.h>
+#include <itkSignedDanielssonDistanceMapImageFilter.h>
+#include <time_stamp.h>    // for creating minc style history entry
+#include "itkMincImageIOFactory.h"
+#include "itkMincImageIO.h"
+#include "minc_helpers.h"
+
+//#include <minc_wrappers.h>
+
+using namespace minc;
+using namespace std;
+void show_usage(const char *name)
+{
+  std::cerr 
+    << "Usage: "<<name<<" <input> <output> " << endl
+    << "--verbose be verbose "    << endl
+    << "--clobber clobber output files"<<endl
+    << "--signed produce signed distance map"<<endl;
+}
+
+int main (int argc, char **argv)
+{
+  
+  int verbose=1;
+  double sigma=0.5;
+  double keep=1.0;
+  int order=5;
+  int approx=0;
+  int ss=0;
+  int clobber=0;
+  char *history = time_stamp(argc, argv); 
+
+  //int voxel_neibourhood=5;
+  static struct option long_options[] = { 
+    {"clobber", no_argument, &clobber, 1},
+    {"verbose", no_argument, &verbose, 1},
+    {"quiet", no_argument, &verbose, 0},
+    {"signed",no_argument, &ss, 1},
+    {0, 0, 0, 0}
+  };
+  
+  for (;;) {
+    /* getopt_long stores the option index here. */
+    int option_index = 0;
+
+    int c = getopt_long (argc, argv, "vq", long_options, &option_index);
+
+    /* Detect the end of the options. */
+    if (c == -1) break;
+
+    switch (c)
+    {
+    //  case 'n':
+    //    voxel_neibourhood=atoi(optarg);break;
+      case 0:
+        break;
+      case '?':
+        /* getopt_long already printed an error message. */
+      default:
+        show_usage (argv[0]);
+        return 1;
+    }
+  }
+  if ((argc - optind) < 2) {
+    show_usage (argv[0]);
+    return 1;
+  }
+  std::string input_f=argv[optind],  out_f=argv[optind+1];
+  
+  // check if the file already present
+  if (!clobber && !access (out_f.c_str (), F_OK))
+  {
+    cerr << out_f.c_str () << " Exists!" << endl;
+    return 1;
+  }
+    
+  try
+  {
+    itk::ObjectFactoryBase::RegisterFactory(itk::MincImageIOFactory::New());
+    itk::ImageFileReader<minc::mask3d >::Pointer reader = itk::ImageFileReader<minc::mask3d >::New();
+    
+    //initializing the reader
+    reader->SetFileName(input_f.c_str());
+    reader->Update();
+    
+    minc::mask3d::Pointer input=reader->GetOutput();
+    minc::image3d::Pointer output;
+    
+    typedef itk::DanielssonDistanceMapImageFilter< minc::mask3d, minc::image3d >
+            DistanceMapFilter;
+    typedef itk::SignedDanielssonDistanceMapImageFilter< minc::mask3d, minc::image3d >
+        SignedDistanceMapFilter;
+    
+    if(ss)
+    {
+      SignedDistanceMapFilter::Pointer dist(SignedDistanceMapFilter::New());
+      dist->SetInput(input);
+      dist->Update();
+      output=dist->GetOutput();
+    } else {
+      DistanceMapFilter::Pointer dist(DistanceMapFilter::New());
+      dist->SetInput(input);
+      dist->Update();
+      output=dist->GetOutput();
+    }
+    
+    minc::copy_metadata(output,input);
+    minc::append_history(output,history);
+    free(history);
+    
+    itk::ImageFileWriter< minc::image3d >::Pointer writer = itk::ImageFileWriter<minc::image3d >::New();
+    writer->SetFileName(out_f.c_str());
+    writer->SetInput( output );
+    writer->Update();
+    
+  } catch (const minc::generic_error & err) {
+    cerr << "Got an error at:" << err.file () << ":" << err.line () << endl;
+    cerr << err.msg()<<endl;
+    return 1;
+  }
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/minc4itk/examples/itk_dti.cpp
@@ -0,0 +1,148 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       :  itk_dti
+@DESCRIPTION:  an example of processing DTI information
+@COPYRIGHT  :
+              Copyright 2011 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include <iostream>
+
+#include <itkMetaDataObject.h>
+#include <itkVectorImage.h>
+
+#include <itkImage.h>
+
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+#include <itkImageIOFactory.h>
+#include <itkDiffusionTensor3DReconstructionImageFilter.h>
+#include <itkTensorFractionalAnisotropyImageFilter.h>
+
+#include "itkMincImageIOFactory.h"
+#include "itkMincImageIO.h"
+
+typedef itk::VectorImage<float, 3>  DTIImageType;
+typedef itk::DiffusionTensor3DReconstructionImageFilter<float,float,float> DtiReconstructionFilter;
+typedef itk::Image< itk::DiffusionTensor3D< float >, 3 > TensorImage;
+typedef DtiReconstructionFilter::GradientDirectionContainerType Gradients;
+typedef itk::Image<float,3> faImage;
+typedef itk::TensorFractionalAnisotropyImageFilter<TensorImage,faImage > FAFilter;
+
+
+// a helper function for minc reading
+template <class T> typename T::Pointer load_minc(const char *file)
+{
+  typedef itk::MincImageIO ImageIOType;
+  ImageIOType::Pointer minc2ImageIO = ImageIOType::New();
+     
+  typename itk::ImageFileReader<T>::Pointer reader = itk::ImageFileReader<T>::New();
+    
+  reader->SetFileName(file);
+  reader->SetImageIO( minc2ImageIO );
+  reader->Update();
+    
+  return reader->GetOutput();
+}
+
+// a helper function for minc writing
+template <class T> void save_minc(const char *file,typename T::ConstPointer img)
+{
+  typedef itk::MincImageIO ImageIOType;
+  ImageIOType::Pointer minc2ImageIO = ImageIOType::New();
+     
+  typename itk::ImageFileWriter< T >::Pointer writer = itk::ImageFileWriter<T>::New();
+  writer->SetFileName(file);
+  writer->SetImageIO( minc2ImageIO );
+  writer->SetInput( img );
+  writer->Update();
+}
+
+
+int main(int argc,char **argv)
+{
+  if(argc<3)
+  {
+    std::cerr<<"Usage:"<<argv[0]<<" <in.mnc> <out_tensor.mnc> <out_eign.mnc> "<<std::endl;
+    return 1;
+  }
+  
+  try
+  {
+    std::cout<<"Reading "<<argv[1]<<"..."<<std::endl;
+    
+    typedef itk::MincImageIO ImageIOType;
+    ImageIOType::Pointer minc2ImageIO = ImageIOType::New();
+    DTIImageType::Pointer img=load_minc<DTIImageType>(argv[1]);
+    DtiReconstructionFilter::Pointer filter=DtiReconstructionFilter::New();
+    filter->SetNumberOfThreads(1); //as per request in documentation
+    
+    //extracting the parameters of acquisition from the metadata
+    typedef std::vector<double> double_vector;
+    double_vector bvalues,direction_x,direction_y,direction_z;
+
+    //making sure that all vcrtors contain the same number of parameters (just in case)
+    if(!itk::ExposeMetaData<double_vector>( img->GetMetaDataDictionary() , "acquisition:bvalues",bvalues) ||
+        !itk::ExposeMetaData<double_vector>( img->GetMetaDataDictionary() , "acquisition:direction_x",direction_x) ||
+        !itk::ExposeMetaData<double_vector>( img->GetMetaDataDictionary() , "acquisition:direction_y",direction_y) ||
+        !itk::ExposeMetaData<double_vector>( img->GetMetaDataDictionary() , "acquisition:direction_z",direction_z))
+    {
+      std::cerr<<"Image doesn't have information on DTI gradients, can't process!"<<std::endl;
+      return 2;
+    }
+    if(bvalues.size()!=direction_x.size() || 
+       bvalues.size()!=direction_y.size() ||
+       bvalues.size()!=direction_z.size() )
+    {
+      std::cerr<<"Different number of components of gradients"<<std::endl;
+        return 2;
+    }
+    std::cout<<"Found "<<bvalues.size()<<" gradient directions"<<std::endl;
+    
+    //converting metadata representation to the format used by DiffusionTensor3DReconstructionImageFilter
+    Gradients::Pointer gradients=Gradients::New();
+    gradients->resize(direction_x.size());
+    double bval=0;
+    //copying values one-by-one
+    for(int i=0;i<bvalues.size();i++)
+      if(bval<bvalues[i]) bval=bvalues[i];
+    
+    for(int i=0;i<direction_x.size();i++)
+    {
+      (*gradients)[i][0]=direction_x[i]*sqrt(bvalues[i]/bval);
+      (*gradients)[i][1]=direction_y[i]*sqrt(bvalues[i]/bval);
+      (*gradients)[i][2]=direction_z[i]*sqrt(bvalues[i]/bval);
+    }
+    
+    std::cout<<"Calculating tensor..."<<std::endl;
+    filter->SetGradientImage(gradients,img);
+    filter->SetBValue(bval);
+    filter->Update();
+    
+    std::cout<<"Writing "<<argv[2]<<"..."<<std::endl;
+    save_minc<TensorImage>(argv[2],filter->GetOutput() );
+    std::cout<<"Calculating FA ..."<<std::endl;
+    
+    FAFilter::Pointer fa=FAFilter::New();
+    fa->SetInput(filter->GetOutput());
+    fa->SetNumberOfThreads(1); //just in case
+    fa->Update();
+    
+    std::cout<<"Writing "<<argv[3]<<"..."<<std::endl;
+    save_minc<faImage>(argv[3],fa->GetOutput() );
+    
+  }
+  catch( itk::ExceptionObject & err )
+  {
+    std::cerr << "ExceptionObject caught !" << std::endl;
+    std::cerr << err << std::endl;
+    return 2;
+  }
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/minc4itk/examples/itk_resample.cpp
@@ -0,0 +1,259 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       :  itk_resample
+@DESCRIPTION:  an example of using spline itnerpolation with MINC xfm transform
+@COPYRIGHT  :
+              Copyright 2011 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include <iostream>
+#include <fstream>
+#include <getopt.h>
+#include <vector>
+#include <valarray>
+#include <math.h>
+#include <limits>
+#include <unistd.h>
+
+#include <itkResampleImageFilter.h>
+#include <itkAffineTransform.h>
+#include <itkNearestNeighborInterpolateImageFunction.h>
+#include <itkBSplineInterpolateImageFunction.h>
+#include <minc_general_transform.h>
+
+#include <unistd.h>
+#include <getopt.h>
+#include <time_stamp.h>    // for creating minc style history entry
+
+
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+#include <itkImageIOFactory.h>
+
+#include "itkMincImageIOFactory.h"
+#include "itkMincImageIO.h"
+#include "minc_helpers.h"
+
+//typedef itk::MincImageIO ImageIOType;
+typedef itk::BSplineInterpolateImageFunction< minc::image3d, double, double >  InterpolatorType;
+typedef itk::ResampleImageFilter<minc::image3d, minc::image3d> FilterType;
+typedef minc::XfmTransform<double,3,3>  TransformType;
+
+using namespace  std;
+
+void show_usage (const char * prog)
+{
+  std::cerr 
+    << "Usage: "<<prog<<" <input> <output.mnc> " << std::endl
+    << "--clobber overwrite files"    << std::endl
+    << "--like <example> (default behaviour analogous to use_input_sampling)"<<std::endl
+    << "--transform <xfm_transform> "<<std::endl
+    << "--order <n> spline order, default 2 "<<std::endl
+    << "--uniformize <step> - will make a volume with uniform step size and no direction cosines" << std::endl
+    << "--invert_transform  - apply inverted transform"<<std::endl;
+}
+
+void generate_uniform_sampling(FilterType* flt, const minc::image3d* img,double step)
+{
+  //obtain physical coordinats of all image corners
+  minc::image3d::RegionType r=img->GetLargestPossibleRegion();
+  std::vector<double> corner[3];
+  for(int i=0;i<8;i++)
+  {
+    minc::image3d::IndexType idx;
+    minc::image3d::PointType c;
+    idx[0]=r.GetIndex()[0]+r.GetSize()[0]*(i%2);
+    idx[1]=r.GetIndex()[1]+r.GetSize()[1]*((i/2)%2);
+    idx[2]=r.GetIndex()[2]+r.GetSize()[2]*((i/4)%2);
+    img->TransformIndexToPhysicalPoint(idx,c);
+    for(int j=0;j<3;j++)
+      corner[j].push_back(c[j]);
+  }
+  minc::image3d::IndexType start;
+  FilterType::SizeType size;
+  FilterType::OriginPointType org;
+  minc::image3d::SpacingType spc;
+  spc.Fill(step);
+  for(int j=0;j<3;j++)
+  {
+    std::sort(corner[j].begin(),corner[j].end());
+    size[j]=ceil((corner[j][7]-corner[j][0])/step);
+    org[j]=corner[j][0];
+  }
+  minc::image3d::DirectionType identity;
+  identity.SetIdentity();
+  flt->SetOutputDirection(identity);
+  start.Fill(0);
+  flt->SetOutputStartIndex(start);
+  flt->SetSize(size);
+  flt->SetOutputOrigin(org);
+  flt->SetOutputSpacing(spc);
+}
+
+int main (int argc, char **argv)
+{
+  int verbose=0, clobber=0,skip_grid=0;
+  int order=2;
+  std::string like_f,xfm_f,output_f,input_f;
+  double uniformize=0.0;
+  int invert=0;
+  char *history = time_stamp(argc, argv); 
+  
+  static struct option long_options[] = {
+		{"verbose", no_argument,       &verbose, 1},
+		{"quiet",   no_argument,       &verbose, 0},
+		{"clobber", no_argument,       &clobber, 1},
+		{"like",    required_argument, 0, 'l'},
+		{"transform",    required_argument, 0, 't'},
+    {"order",    required_argument, 0, 'o'},
+    {"uniformize",    required_argument, 0, 'u'},
+    {"invert_transform", no_argument, &invert, 1},
+		{0, 0, 0, 0}
+		};
+  
+  for (;;) {
+      /* getopt_long stores the option index here. */
+      int option_index = 0;
+
+      int c = getopt_long (argc, argv, "vqcl:t:o:u:", long_options, &option_index);
+
+      /* Detect the end of the options. */
+      if (c == -1) break;
+
+      switch (c)
+			{
+			case 0:
+				break;
+			case 'v':
+				cout << "Version: 0.1" << endl;
+				return 0;
+      case 'l':
+        like_f=optarg; break;
+      case 't':
+        xfm_f=optarg; break;
+      case 'o':
+        order=atoi(optarg);break;
+      case 'u':
+        uniformize=atof(optarg);break;
+			case '?':
+				/* getopt_long already printed an error message. */
+			default:
+				show_usage (argv[0]);
+				return 1;
+			}
+    }
+
+	if ((argc - optind) < 2) {
+		show_usage(argv[0]);
+		return 1;
+	}
+  input_f=argv[optind];
+  output_f=argv[optind+1];
+  
+  if (!clobber && !access (output_f.c_str (), F_OK))
+  {
+    std::cerr << output_f.c_str () << " Exists!" << std::endl;
+    return 1;
+  }
+  
+	try
+  {
+    itk::ObjectFactoryBase::RegisterFactory(itk::MincImageIOFactory::New());
+    itk::ImageFileReader<minc::image3d >::Pointer reader = itk::ImageFileReader<minc::image3d >::New();
+    
+    //initializing the reader
+    reader->SetFileName(input_f.c_str());
+    reader->Update();
+    
+		minc::image3d::Pointer in=reader->GetOutput();
+
+		FilterType::Pointer filter  = FilterType::New();
+    
+    //creating coordinate transformation objects
+		TransformType::Pointer transform = TransformType::New();
+    if(!xfm_f.empty())
+    {
+      //reading a minc style xfm file
+      transform->OpenXfm(xfm_f.c_str());
+      if(!invert) transform->Invert(); //should be inverted by default to walk through target space
+      filter->SetTransform( transform );
+    }
+
+    //creating the interpolator
+		InterpolatorType::Pointer interpolator = InterpolatorType::New();
+		interpolator->SetSplineOrder(order);
+		filter->SetInterpolator( interpolator );
+		filter->SetDefaultPixelValue( 0 );
+    
+    //this is for processing using batch system
+    filter->SetNumberOfThreads(1);
+    
+    minc::image3d::Pointer like=0;
+    if(!like_f.empty())
+    {
+      itk::ImageFileReader<minc::image3d >::Pointer reader = itk::ImageFileReader<minc::image3d >::New();
+      reader->SetFileName(like_f.c_str());
+      reader->Update();
+      if(uniformize!=0.0)
+      {
+        generate_uniform_sampling(filter,reader->GetOutput(),uniformize);
+      } else {
+        filter->SetOutputParametersFromImage(reader->GetOutput());
+        filter->SetOutputDirection(reader->GetOutput()->GetDirection());
+      }
+      like=reader->GetOutput();
+      like->DisconnectPipeline();
+    }
+    else
+    {
+      if(uniformize!=0.0)
+      {
+        generate_uniform_sampling(filter,in,uniformize);
+      } else {
+        //we are using original sampling
+        filter->SetOutputParametersFromImage(in);
+        filter->SetOutputDirection(in->GetDirection());
+      }
+    }
+    
+		filter->SetInput(in);
+    filter->Update();
+    //copy the metadate information, for some reason it is not preserved
+    //filter->GetOutput()->SetMetaDataDictionary(reader->GetOutput()->GetMetaDataDictionary());
+    minc::image3d::Pointer out=filter->GetOutput();
+    minc::copy_metadata(out,in);
+    minc::append_history(out,history);
+    free(history);
+    
+    //correct dimension order
+    if(like.IsNotNull())
+      minc::copy_dimorder(out,like);
+    
+    //generic file writer
+    itk::ImageFileWriter< minc::image3d >::Pointer writer = itk::ImageFileWriter<minc::image3d >::New();
+    writer->SetFileName(output_f.c_str());
+     
+    writer->SetInput( out );
+    //writer->UseInputMetaDataDictionaryOn();
+    
+    writer->Update();
+    
+		return 0;
+	} catch (const minc::generic_error & err) {
+    cerr << "Got an error at:" << err.file () << ":" << err.line () << endl;
+    return 1;
+  }
+  catch( itk::ExceptionObject & err )
+  {
+    std::cerr << "ExceptionObject caught !" << std::endl;
+    std::cerr << err << std::endl;
+    return 2;
+  }
+	return 0;
+};
new file mode 100644
--- /dev/null
+++ b/minc4itk/examples/volume_2_csv.cpp
@@ -0,0 +1,156 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       :  volume_2_csv
+@DESCRIPTION:  an example of converting a minc file volume to a text format
+@COPYRIGHT  :
+              Copyright 2011 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include <iostream>
+#include <fstream>
+#include <getopt.h>
+#include <vector>
+#include <valarray>
+#include <math.h>
+#include <limits>
+#include <unistd.h>
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+#include <itkImageIOFactory.h>
+
+#include "itkMincImageIOFactory.h"
+#include "itkMincImageIO.h"
+
+#include "minc_helpers.h"
+
+
+using namespace  std;
+using namespace  minc;
+
+void show_usage (const char * prog)
+{
+  std::cerr<<"Usage:"<<prog<<" in.mnc out.csv --mask <mask> --clobber --terse"<<endl; 
+}
+
+typedef itk::MincImageIO ImageIOType;
+
+
+int main (int argc, char **argv)
+{
+  std::string mask_f;
+  int verbose=0,clobber=0;
+  int terse=0;
+  static struct option long_options[] = {
+		{"verbose", no_argument,       &verbose, 1},
+		{"quiet",   no_argument,       &verbose, 0},
+		{"clobber", no_argument,       &clobber, 1},
+		{"mask",    required_argument,   0, 'm'},
+    {"terse",   no_argument,       &terse, 1},
+		{0, 0, 0, 0}
+		};
+  
+  for (;;) {
+      /* getopt_long stores the option index here. */
+      int option_index = 0;
+
+      int c = getopt_long (argc, argv, "m:vd:k:i:", long_options, &option_index);
+
+      /* Detect the end of the options. */
+      if (c == -1) break;
+
+      switch (c)
+			{
+			case 0:
+				break;
+			case 'v':
+				cout << "Version: 0.1" << endl;
+				return 0;
+      case 'm':
+        mask_f=optarg; break;
+			case '?':
+				/* getopt_long already printed an error message. */
+			default:
+				show_usage (argv[0]);
+				return 1;
+			}
+    }
+
+	if((argc - optind) < 2) {
+		show_usage (argv[0]);
+		return 1;
+	}
+  if (!clobber && !access(argv[optind+1], F_OK))
+  {
+    cerr << argv[optind+1] << " Exists!" << endl;
+    return 1;
+  }
+  
+	try
+  {
+		minc::mask3d::Pointer  mask(minc::mask3d::New());
+    
+    //creating a minc reader
+    ImageIOType::Pointer minc2ImageIO = ImageIOType::New();
+    
+    itk::ImageFileReader<minc::image3d >::Pointer reader = itk::ImageFileReader<minc::image3d >::New();
+    //initializing the reader
+    reader->SetFileName(argv[optind]);
+    reader->SetImageIO( minc2ImageIO );
+    reader->Update();
+    
+		minc::image3d::Pointer img=reader->GetOutput();
+    
+    
+    if(!mask_f.empty())
+    {
+      itk::ImageFileReader<minc::mask3d >::Pointer reader = itk::ImageFileReader<minc::mask3d >::New();
+      //initializing the reader
+      reader->SetFileName(mask_f.c_str());
+      reader->SetImageIO( minc2ImageIO );
+      reader->Update();
+      mask=reader->GetOutput();
+    }
+    const minc::mask3d::RegionType& reg=mask->GetLargestPossibleRegion();
+  
+    ofstream out(argv[optind+1]);
+    if(out.bad())
+      REPORT_ERROR ("can't open file");
+
+    image3d_iterator it(img,img->GetLargestPossibleRegion());
+    if(!terse) out<<"x,y,z,I"<<endl;
+    if(out.bad())
+      REPORT_ERROR ("can't write to file");
+    
+    mask3d::IndexType idx;
+    
+    for(it.GoToBegin();!it.IsAtEnd();++it) {
+      tag_point p;
+      img->TransformIndexToPhysicalPoint(it.GetIndex(),p);
+      
+      if(!mask_f.empty())
+      {
+        mask->TransformPhysicalPointToIndex(p,idx);
+        if(!reg.IsInside(idx) || !mask->GetPixel(idx))
+            continue;
+      }
+      
+      if(terse)
+        out<<it.Value()<<endl;
+      else
+      out<<p[0]<<","<<p[1]<<","<<p[2]<<","<<it.Value()<<endl;
+      if(out.bad())
+        REPORT_ERROR ("can't write to file");
+    }
+		return 0;
+	} catch (const minc::generic_error & err) {
+    cerr << "Got an error at:" << err.file () << ":" << err.line () << endl;
+    return 1;
+  }
+	return 0;
+};
new file mode 100644
--- /dev/null
+++ b/minc4itk/itkMincImageIO.cxx
@@ -0,0 +1,720 @@
+/*=========================================================================
+Program:   Insight Segmentation & Registration Toolkit
+Module:    $RCSfile: itkMincImageIO.cxx,v $
+Language:  C++
+Date:      $Date: 2005/12/08 19:18:48 $
+Version:   $Revision: 1.22 $
+
+Copyright (c) Insight Software Consortium. All rights reserved.
+See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+
+This software is distributed WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#include "itkMincImageIO.h"
+#include "itkIOCommon.h"
+#include "itkExceptionObject.h"
+#include "itkMetaDataObject.h"
+#include <itkMatrix.h>
+#include <itksys/SystemTools.hxx>
+#include <vnl/vnl_math.h>
+#include <zlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+
+using namespace minc;
+
+namespace itk
+{
+
+  MincImageIO::MincImageIO():_rdr(NULL),_wrt(NULL)
+  {
+  }
+  
+  void MincImageIO::clean(void)
+  {
+    if(_rdr) delete _rdr;
+    if(_wrt) delete _wrt;
+    _rdr=NULL;
+    _wrt=NULL;
+  }
+  
+  MincImageIO::~MincImageIO()
+  {
+    clean();
+  }
+  
+  void MincImageIO::PrintSelf(std::ostream& os, Indent indent) const
+  {
+    Superclass::PrintSelf(os, indent);
+    if(_rdr)
+      os<<"MINC file is opened for reading"<<std::endl;
+    if(_wrt)
+      os<<"MINC file is opened for writing"<<std::endl;
+  }
+  
+  
+  bool MincImageIO::CanReadFile( const char* FileNameToRead )
+  {
+    std::string filename = FileNameToRead;
+    //taken from original MINC2ImageIO
+
+    if( filename.empty())
+    {
+      itkDebugMacro(<<"No filename specified.");
+      return false;
+    }
+
+    std::string::size_type mncPos = filename.rfind(".mnc");
+    if ( (mncPos != std::string::npos)
+          && (mncPos == filename.length() - 4) )
+    {
+      return true;
+    }
+
+    mncPos = filename.rfind(".MNC");
+    if ( (mncPos != std::string::npos)
+          && (mncPos == filename.length() - 4) )
+    {
+      return true;
+    }
+
+    mncPos = filename.rfind(".mnc2");
+    if ( (mncPos != std::string::npos)
+          && (mncPos == filename.length() - 5) )
+    {
+      return true;
+    }
+    
+    mncPos = filename.rfind(".MNC2");
+    if ( (mncPos != std::string::npos)
+          && (mncPos == filename.length() - 5) )
+    {
+      return true;
+    }
+    
+    mncPos = filename.rfind(".mnc.gz");
+    if ( (mncPos != std::string::npos)
+          && (mncPos == filename.length() - 7) )
+    {
+      return true;
+    }
+
+    mncPos = filename.rfind(".MNC.GZ");
+    if ( (mncPos != std::string::npos)
+          && (mncPos == filename.length() - 7) )
+    {
+      return true;
+    }
+    
+    return false;
+  }
+  
+  void MincImageIO::ReadImageInformation()
+  {
+    clean();
+    try
+    {
+      _rdr=new minc_1_reader;
+      _rdr->open(m_FileName.c_str(),true); //read in positive direction, always
+      SetNumberOfDimensions((_rdr->ndim(1)>0?1:0)+(_rdr->ndim(2)>0?1:0)+(_rdr->ndim(3)>0?1:0));
+      
+      //SetMetaDataDictionary(thisDic);
+      // set number of dimensions for ITK
+      int image_max_length=_rdr->var_length(MIimagemax);
+      int image_min_length=_rdr->var_length(MIimagemin);
+      bool slice_normalized=image_max_length>1;
+      /*
+      std::cout<<"Image max length="<<image_max_length<<std::endl;
+      std::cout<<"Image min length="<<image_min_length<<std::endl;*/
+      
+      switch(_rdr->datatype())
+      {
+        case NC_BYTE:
+          if(slice_normalized)
+            m_ComponentType=FLOAT;
+          else
+            m_ComponentType=UCHAR;
+          break;
+          
+        case NC_SHORT: 
+          
+          if(slice_normalized)
+            m_ComponentType=FLOAT;
+          else
+            m_ComponentType=_rdr->is_signed()?SHORT:USHORT;
+          break;
+          
+        case NC_INT:
+          if(slice_normalized)
+            m_ComponentType=FLOAT;
+          else
+            m_ComponentType=_rdr->is_signed()?INT:UINT;
+          break;
+          
+        case NC_FLOAT:
+          m_ComponentType=FLOAT;
+          break;
+        
+        case NC_DOUBLE:
+          m_ComponentType=DOUBLE;
+          break;
+        
+        default:
+          throw ExceptionObject(__FILE__,__LINE__,"Unsupported data type");
+      }
+      
+      if(_rdr->ndim(0)==0 && _rdr->ndim(4)==0) //vector dimension
+      {
+        m_PixelType=SCALAR;
+        //SetNumberOfComponents(1);
+      } else {
+        m_PixelType=VECTOR;
+        if(_rdr->ndim(0)>0 && _rdr->ndim(4)>0)
+          throw ExceptionObject(__FILE__,__LINE__,"Combining time and vector dimension in one file is not supported!");
+        SetNumberOfComponents(_rdr->ndim(0)+_rdr->ndim(4));
+      }
+      
+      for(int i=1,c=0; i < 4; i++)
+      {
+        if(_rdr->ndim(i)<=0) continue;
+        SetDimensions(c,_rdr->ndim(i));
+        SetSpacing(c,_rdr->nspacing(i));
+        SetOrigin(c,_rdr->nstart(i));
+        c++;
+      }
+      
+      if(GetNumberOfDimensions()==3)
+      {
+        itk::Matrix< double, 3,3 > dir_cos;
+        for(int i=1; i < 4; i++)
+        {
+          std::vector<double> dc(3);
+          if(_rdr->have_dir_cos(i))
+          {
+            for(int j=0;j<3;j++)
+            {
+              dc[j]=_rdr->ndir_cos(i,j);
+              dir_cos[j][i-1]=_rdr->ndir_cos(i,j);
+            }
+          } else {
+            for(int j=0;j<3;j++)
+            {
+              dc[j]=((i-1)==j?1:0);
+              dir_cos[j][i-1]=((i-1)==j?1:0);
+            }
+          }
+          SetDirection(i-1,dc);
+        }
+        
+        itk::Vector< double,3> origin;
+        itk::Vector< double,3> o_origin;
+        for(int j=0;j<3;j++)
+          o_origin[j]=GetOrigin(j);
+        origin=dir_cos*o_origin;
+        for(int j=0;j<3;j++)
+          SetOrigin(j,origin[j]);
+      } else { //we are not rotating the origin according to direction cosines in this case 
+        for(int i=1,c=0; i < 5; i++)
+        {
+          if(_rdr->ndim(i)<=0) continue;
+          std::vector<double> dc(3);
+          for(int j=0;j<3;j++)
+            dc[j]=_rdr->ndir_cos(i,j);
+          SetDirection(c,dc);
+          c++;
+        }
+      }
+      ComputeStrides();
+      
+      //now, we are just assuming that all the volumes with short,int and float data types are real, 
+      //and those that are char are not 
+      itk::MetaDataDictionary &thisDic=GetMetaDataDictionary();
+      std::string classname(GetNameOfClass());
+      itk::EncapsulateMetaData<std::string>(thisDic,ITK_InputFilterName, classname);
+      //now let's store some metadata
+      //internally image is always stored 
+      
+      /*itk::EncapsulateMetaData<itk::SpatialOrientation::ValidCoordinateOrientationFlags>
+          (thisDic,ITK_CoordinateOrientation, itk::SpatialOrientation::ITK_COORDINATE_ORIENTATION_LPI);*/
+      
+      itk::EncapsulateMetaData(thisDic,"datatype",_rdr->datatype());
+      itk::EncapsulateMetaData(thisDic,"signed"  ,_rdr->is_signed());
+      
+      /*switch(_rdr->datatype())
+      {
+        case NC_SHORT:
+          
+          itk::EncapsulateMetaData<std::string>(thisDic,ITK_OnDiskStorageTypeName,_rdr->is_signed()?std::string(typeid(short).name()):std::string(typeid(unsigned short).name()));
+          break;
+          
+        case NC_BYTE:
+          itk::EncapsulateMetaData<std::string>(thisDic,ITK_OnDiskStorageTypeName,_rdr->is_signed()?std::string(typeid(char).name()):std::string(typeid(unsigned char).name()));
+          break;
+          
+        case NC_FLOAT:
+          itk::EncapsulateMetaData<std::string>(thisDic,ITK_OnDiskStorageTypeName,std::string(typeid(float).name()));
+          break;
+      }*/
+      
+      if(_rdr->ndim(4)) //we have got time dimension
+      {
+        itk::EncapsulateMetaData<double>(thisDic,"tstart",_rdr->nstart(4));
+        itk::EncapsulateMetaData<double>(thisDic,"tstep",_rdr->nspacing(4));
+      }
+      
+      std::vector<std::string> dimorder;
+      for(int i=0;i<_rdr->dim_no();i++)
+      {
+        dimorder.push_back(_rdr->info()[i].name);
+      }
+      itk::EncapsulateMetaData(thisDic,"dimorder", dimorder);
+      itk::EncapsulateMetaData<std::string>(thisDic,"history", _rdr->history());
+      //walk through all the minc attributes, and store them
+      for(int i=0;i<_rdr->var_number();i++)
+      {
+        std::string var=_rdr->var_name(i);
+        
+        if(var=="rootvariable" || 
+           var=="image" || 
+           var=="image-min" || 
+           var=="image-max" ||
+           var=="xspace" || 
+           var=="yspace" ||
+           var=="zspace" || 
+           var=="time" ||
+           var=="vector_dimension"  )
+          continue;
+        int var_id=_rdr->var_id(var.c_str());
+        for(int j=0;j<_rdr->att_number(var_id);j++)
+        {
+          std::string att=_rdr->att_name(var_id,j);
+          std::string path=var+":"+att;
+          //std::cout<<path.c_str()<<" ";
+          switch(_rdr->att_type(var_id,att.c_str()))
+          {
+            case NC_CHAR:
+              itk::EncapsulateMetaData<std::string>(thisDic,path, _rdr->att_value_string(var_id,att.c_str()));
+              //std::cout<<"string";
+              break;
+            case NC_INT:
+              itk::EncapsulateMetaData<std::vector<int> >(thisDic,path, _rdr->att_value_int(var_id,att.c_str()));
+              //std::cout<<"int";
+              break;
+            case NC_DOUBLE:
+              itk::EncapsulateMetaData<std::vector<double> >(thisDic,path, _rdr->att_value_double(var_id,att.c_str()));
+              //std::cout<<"double";
+              break;
+            case NC_SHORT:
+              itk::EncapsulateMetaData<std::vector<short> >(thisDic,path, _rdr->att_value_short(var_id,att.c_str()));
+              break;
+            case NC_BYTE:
+              itk::EncapsulateMetaData<std::vector<unsigned char> >(thisDic,path, _rdr->att_value_byte(var_id,att.c_str()));
+              break;
+            default:
+              //std::cout<<"Unknown";
+              break; //don't know what it is, skipping for now!  
+          }
+          //std::cout<<std::endl;
+        }
+      }
+      
+    } catch(const minc::generic_error & err) {
+      throw ExceptionObject(__FILE__,__LINE__,"Error reading minc file");
+    }
+  }
+    
+  void MincImageIO::Read(void* buffer)
+  {
+    //TODO: add support for IORegion ?
+    //ImageIORegion regionToRead = this->GetIORegion();
+    switch(GetComponentType())
+    {
+      case CHAR:
+      case UCHAR:
+        _rdr->setup_read_byte(false);
+        load_non_standard_volume<unsigned char>(*_rdr,(unsigned char*)buffer);
+        break;
+      case INT:
+        _rdr->setup_read_int(false);
+        load_non_standard_volume<int>(*_rdr,(int*)buffer);
+        break;
+      case UINT:
+        _rdr->setup_read_uint(false);
+        load_non_standard_volume<unsigned int>(*_rdr,(unsigned int*)buffer);
+        break;
+      case SHORT:
+        _rdr->setup_read_short(false);
+        load_non_standard_volume<short>(*_rdr,(short*)buffer);
+        break;
+      case USHORT:
+        _rdr->setup_read_ushort(false);
+        load_non_standard_volume<unsigned short>(*_rdr,(unsigned short*)buffer);
+        break;
+      case FLOAT:
+        _rdr->setup_read_float();
+        load_non_standard_volume<float>(*_rdr,(float*)buffer);
+        break;
+      case DOUBLE:
+        _rdr->setup_read_double();
+        load_non_standard_volume<double>(*_rdr,(double*)buffer);
+        break;
+      default:
+        throw ExceptionObject(__FILE__, __LINE__,"Unsupported data type");
+    }
+    delete _rdr;
+    _rdr=NULL;
+  }
+  
+  bool MincImageIO::CanWriteFile(const char * FileNameToWrite)
+  {
+    std::string filename = FileNameToWrite;
+    //taken from original MINC2ImageIO
+
+    if( filename.empty())
+    {
+      itkDebugMacro(<<"No filename specified.");
+      return false;
+    }
+
+    std::string::size_type mncPos = filename.rfind(".mnc");
+    if ( (mncPos != std::string::npos)
+          && (mncPos == filename.length() - 4) )
+    {
+      return true;
+    }
+
+    mncPos = filename.rfind(".MNC");
+    if ( (mncPos != std::string::npos)
+          && (mncPos == filename.length() - 4) )
+    {
+      return true;
+    }
+
+    mncPos = filename.rfind(".mnc2");
+    if ( (mncPos != std::string::npos)
+          && (mncPos == filename.length() - 5) )
+    {
+      return true;
+    }
+    
+    mncPos = filename.rfind(".MNC2");
+    if ( (mncPos != std::string::npos)
+          && (mncPos == filename.length() - 5) )
+    {
+      return true;
+    }
+    
+    return false;
+  }
+  
+  void MincImageIO::WriteImageInformation(void) 
+  {
+    try
+    {
+      MetaDataDictionary &thisDic=GetMetaDataDictionary();
+      nc_type datatype;
+      bool is_signed=false;
+      bool have_vectors=false;
+      bool have_time=false;
+      
+      switch(GetComponentType())
+      {
+        case UCHAR:
+        case CHAR:
+          datatype=NC_BYTE;
+          is_signed=false;
+          break;
+        case SHORT:
+          datatype=NC_SHORT;
+          is_signed=true;
+          break;
+        case USHORT:
+          datatype=NC_SHORT;
+          is_signed=false;
+          break;
+        case INT:
+          datatype=NC_INT;
+          is_signed=true;
+          break;
+        case UINT:
+          datatype=NC_INT;
+          is_signed=false;
+       
+          break;
+        case FLOAT:
+          //let's see if there is metadata available
+          nc_type _datatype;
+          bool _is_signed;
+          if( itk::ExposeMetaData(thisDic,"datatype",_datatype) &&
+              itk::ExposeMetaData(thisDic,"signed",_is_signed) ) 
+          {
+            datatype=_datatype;
+            is_signed=_is_signed;
+          } else {
+            datatype=NC_FLOAT;
+            is_signed=true;
+          }
+          
+          break;
+        case DOUBLE:
+          datatype=NC_DOUBLE;
+          is_signed=true;
+          break;
+        default:
+        {
+          throw ExceptionObject(__FILE__, __LINE__,"Unsupported data type");
+        }
+      }
+      std::vector<std::string> dimorder;
+      std::vector<int> dimmap(5,-1);
+      minc_info info;
+      
+      if(GetNumberOfComponents()>1 && GetNumberOfComponents()<=3 ) 
+      {
+        have_vectors=true;
+        have_time=false;
+      } else if(GetNumberOfComponents()>3||GetNumberOfDimensions()>3) {
+        have_vectors=false;
+        have_time=true;
+      }
+      
+      if(itk::ExposeMetaData(thisDic,"dimorder",dimorder))
+      {
+        //dimmap.resize(dimorder.size());
+        for(int i=0,j=0;i<dimorder.size();i++)
+        {
+          if(dimorder[i]==MIvector_dimension && have_vectors)
+          {
+            dimmap[0]=j++;
+          }
+          else if(dimorder[i]==MItime && have_time)
+          {
+            dimmap[4]=j++;
+          } else if(dimorder[i]==MIxspace) {
+            dimmap[1]=j++;
+          } else if(dimorder[i]==MIyspace) {
+            dimmap[2]=j++;
+          } else if(dimorder[i]==MIzspace) {
+            dimmap[3]=j++;
+          }
+        }
+      } else {
+        if(have_vectors)
+        {
+          dimmap[0]=0;
+        } else if(have_time) {
+          have_vectors=false;
+          have_time=true;
+          dimmap[GetNumberOfDimensions()+1]=GetNumberOfDimensions();
+        }
+        dimmap[1]=(have_vectors?1:0)+0;
+        dimmap[2]=(have_vectors?1:0)+1;
+        dimmap[3]=(have_vectors?1:0)+2;
+      }
+      
+      int dim_no=GetNumberOfDimensions()+(have_vectors||have_time?1:0);
+      info.resize(dim_no);
+      
+/*      std::cout<<"dimmap:";
+      for(int i=0;i<5;i++)
+      {
+        std::cout<<dimmap[i]<<",";
+      }
+      std::cout<<std::endl;*/
+      
+      for(int i=0;i<GetNumberOfDimensions();i++)
+      {
+        int _i=dimmap[i+1];//GetNumberOfDimensions()-i-1+(have_vectors?1:0);
+        if(_i<0) 
+        {
+          throw ExceptionObject(__FILE__, __LINE__,"Internal error");
+        }
+         //ERROR!
+        info[_i].length=GetDimensions(i);
+        info[_i].step=GetSpacing(i);
+        info[_i].start=GetOrigin(i);
+        info[_i].have_dir_cos=true;
+        for(int j=0;j<3;j++)
+          info[_i].dir_cos[j]=GetDirection(i)[j];
+        
+        switch(i)
+        {
+          case 0:
+            info[_i].dim=dim_info::DIM_X;
+            break;
+          case 1:
+            info[_i].dim=dim_info::DIM_Y;
+            break;
+          case 2:
+            info[_i].dim=dim_info::DIM_Z;
+            break;
+        }
+      }
+      if(GetNumberOfDimensions()==3) //we are only rotating 3D volumes
+      {
+        vnl_vector< double> start(3);
+        vnl_vector< double> vorigin(3);
+        itk::Matrix< double, 3,3 > _dir_cos;
+        for(int i=0;i<3;i++)
+        {
+          vorigin[i]=GetOrigin(i);
+          for(int j=0;j<3;j++)
+            _dir_cos[j][i]=GetDirection(i)[j];
+        }
+        start=_dir_cos.GetInverse()*vorigin; //this is not optimal
+        for(int i=0;i<3;i++)
+        {
+          int _i=dimmap[i+1];
+          info[_i].start=start[i];
+        }
+      }
+      //here we assume that we had a grid file
+      if(have_vectors)
+      {
+        int _i=dimmap[0];
+        info[_i].length=GetNumberOfComponents();
+        info[_i].step=1;
+        info[_i].start=0;
+        info[_i].dim=dim_info::DIM_VEC;
+        info[_i].have_dir_cos=false;
+      } else if(have_time){
+        int _i=dimmap[4];
+        info[_i].length=GetNumberOfComponents();
+        double tstep=1;
+        double tstart=0;
+        itk::ExposeMetaData(thisDic,"tstep",tstep);
+        itk::ExposeMetaData(thisDic,"tstart",tstart);
+        
+        info[_i].step=tstep;
+        info[_i].start=tstart;
+        info[_i].dim=dim_info::DIM_TIME;
+        info[_i].have_dir_cos=false;
+      }
+      
+/*      std::cout<<"info:";
+      for(int i=0;i<info.size();i++)
+      {
+        switch(info[i].dim)
+        {
+          case dim_info::DIM_VEC:
+            std::cout<<"vector_dimension,";break;
+          case dim_info::DIM_Z:
+            std::cout<<"zspace,";break;
+          case dim_info::DIM_Y:
+            std::cout<<"yspace,";break;
+          case dim_info::DIM_X:
+            std::cout<<"xspace,";break;
+          default: std::cout<<"Unknown! ";break;
+            
+        }
+      }
+      std::cout<<std::endl;      */
+      
+      //TODO:  shuffle info based on the dimnames
+      _wrt=new minc_1_writer;
+      _wrt->open(this->GetFileName(),
+                 info,
+                 (datatype==NC_FLOAT||datatype==NC_DOUBLE)?
+                     dim_no:(have_time?dim_no-2:dim_no-1),
+                 datatype,is_signed);
+      
+      //let's write some meta information if there is any 
+      for(MetaDataDictionary::ConstIterator it=thisDic.Begin();it!=thisDic.End();++it)
+      {
+        const char *d=strchr((*it).first.c_str(),':');
+        if(d)
+        {
+          std::string var((*it).first.c_str(),d-(*it).first.c_str());
+          std::string att(d+1);
+          itk::MetaDataObjectBase *bs=(*it).second;
+          const char *tname=bs->GetMetaDataObjectTypeName();
+          //std::cout<<var.c_str()<<"\t"<<att.c_str()<<"\t"<<tname<<std::endl;
+          
+          //THIS is not good OO style at all :(
+          if(!strcmp(tname,typeid(std::string).name()))
+          {
+            _wrt->insert(var.c_str(),att.c_str(),
+              dynamic_cast<MetaDataObject<std::string> *>(bs )->GetMetaDataObjectValue().c_str());
+          } else if(!strcmp(tname,typeid(std::vector<double>).name())) {
+            _wrt->insert(var.c_str(),att.c_str(),
+              dynamic_cast<MetaDataObject<std::vector<double> > * >(bs)->GetMetaDataObjectValue());
+          } else if(!strcmp(tname,typeid(std::vector<int>).name())) {
+            _wrt->insert(var.c_str(),att.c_str(),
+              dynamic_cast<MetaDataObject<std::vector<int> > * >(bs)->GetMetaDataObjectValue());
+          } else if(!strcmp(tname,typeid(std::vector<short>).name())) {
+            _wrt->insert(var.c_str(),att.c_str(),
+                         dynamic_cast<MetaDataObject<std::vector<short> > * >(bs)->GetMetaDataObjectValue());
+          } else if(!strcmp(tname,typeid(std::vector<unsigned char>).name())) {
+            _wrt->insert(var.c_str(),att.c_str(),
+                         dynamic_cast<MetaDataObject<std::vector<unsigned char> > * >(bs)->GetMetaDataObjectValue());
+          }
+        } else if((*it).first=="history") {
+          itk::MetaDataObjectBase *bs=(*it).second;
+          _wrt->append_history(dynamic_cast<MetaDataObject<std::string> *>(bs)->GetMetaDataObjectValue().c_str());
+        }
+        
+      }
+    } catch(const minc::generic_error & err) {
+      ExceptionObject exception(err.file(), err.line());
+      std::string ErrorMessage="MINC IO error:";
+      ErrorMessage+=err.msg();
+      exception.SetDescription(ErrorMessage.c_str());
+      throw exception;
+    }
+    return;
+  }
+  
+  void MincImageIO::Write( const void* buffer)
+  {
+    try
+    {
+      this->WriteImageInformation(); //Write the image Information before writing data
+      
+      switch(this->GetComponentType())
+      {
+        case UCHAR:
+        case CHAR:
+          _wrt->setup_write_byte(false);
+          save_non_standard_volume<unsigned char>(*_wrt,(const unsigned char*)buffer);
+          break;
+        case SHORT:
+          _wrt->setup_write_short();
+          save_non_standard_volume<short>(*_wrt,(const short*)buffer);
+          break;
+        case USHORT:
+          _wrt->setup_write_ushort();
+          save_non_standard_volume<unsigned short>(*_wrt,(const unsigned short*)buffer);
+          break;
+        case INT:
+          _wrt->setup_write_int();
+          save_non_standard_volume<int>(*_wrt,(const int*)buffer);
+          break;
+        case UINT:
+          _wrt->setup_write_uint();
+          save_non_standard_volume<unsigned int>(*_wrt,(const unsigned int*)buffer);
+          break;
+        case FLOAT:
+          _wrt->setup_write_float();
+          save_non_standard_volume<float>(*_wrt,(const float*)buffer);
+          break;
+        case DOUBLE:
+          _wrt->setup_write_double();
+          save_non_standard_volume<double>(*_wrt,(const double*)buffer);
+          break;
+        default:
+          throw ExceptionObject(__FILE__,__LINE__,"Unsupported data type");
+      }
+      //finish writing, cleanup
+      delete _wrt;
+      _wrt=NULL;
+    } catch(const minc::generic_error & err) {
+      throw ExceptionObject(__FILE__, __LINE__,"Error reading minc file");
+    }
+    
+  }
+} // end namespace itk
new file mode 100644
--- /dev/null
+++ b/minc4itk/itkMincImageIO.h
@@ -0,0 +1,99 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : 
+@DESCRIPTION: 
+@COPYRIGHT  :
+              Copyright 2006 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#ifndef __itkMincImageIO_h
+#define __itkMincImageIO_h
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4786 )
+#endif
+
+#include <itkImageIOBase.h>
+#include <minc_1_simple.h>
+
+namespace itk
+{
+
+ /** \class MincImageIO
+  *
+  * \author Vladimir S. Fonov
+  * \brief Class that defines how to read Minc file format.
+  * MINC IMAGE FILE FORMAT 
+  *
+  * \ingroup IOFilters
+  */
+  class ITK_EXPORT MincImageIO: public ImageIOBase
+  {
+  public:
+    /** Standard class typedefs. */
+    typedef MincImageIO  Self;
+    typedef ImageIOBase  Superclass;
+    typedef SmartPointer<Self>  Pointer;
+  
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);
+  
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(MincImageIO, Superclass);
+  
+    /*-------- This part of the interfaces deals with reading data. ----- */
+  
+    /** Determine if the file can be read with this ImageIO implementation.
+         * \author Vladimir S. Fonov
+         * \param FileNameToRead The name of the file to test for reading.
+         * \post Sets classes ImageIOBase::m_FileName variable to be FileNameToWrite
+         * \return Returns true if this ImageIO can read the file specified.
+         */
+    virtual bool CanReadFile(const char* FileNameToRead) ;
+  
+    /** Set the spacing and dimension information for the set filename. */
+    virtual void ReadImageInformation();
+  
+    /** Reads the data from disk into the memory buffer provided. */
+    virtual void Read(void* buffer);
+  
+    /*-------- This part of the interfaces deals with writing data. ----- */
+  
+    /** Determine if the file can be written with this ImageIO implementation.
+         * \param FileNameToWrite The name of the file to test for writing.
+         * \author Vladimir S. Fonov
+         * \post Sets classes ImageIOBase::m_FileName variable to be FileNameToWrite
+         * \return Returns true if this ImageIO can write the file specified.
+         */
+    virtual bool CanWriteFile(const char * FileNameToWrite);
+  
+    /** Set the spacing and dimension information for the set filename. */
+    virtual void WriteImageInformation();
+  
+    /** Writes the data to disk from the memory buffer provided.  */
+    virtual void Write(const void* buffer);
+  
+  
+  protected:
+    //! minc 1 reader
+    minc::minc_1_reader *_rdr; 
+    minc::minc_1_writer *_wrt; 
+    MincImageIO();
+    ~MincImageIO();
+    void PrintSelf(std::ostream& os, Indent indent) const;
+  
+    MincImageIO(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+    void clean(void);
+  };
+} // end namespace itk
+
+#endif // __itkMincImageIO_h
new file mode 100644
--- /dev/null
+++ b/minc4itk/itkMincImageIOFactory.cxx
@@ -0,0 +1,40 @@
+#include "itkMincImageIOFactory.h"
+#include "itkCreateObjectFunction.h"
+#include "itkMincImageIO.h"
+#include <itkVersion.h>
+#include <iostream>
+namespace itk
+{
+  void MincImageIOFactory::PrintSelf(std::ostream&, Indent) const
+  {
+    
+  }
+  
+  
+  MincImageIOFactory::MincImageIOFactory()
+  {
+    this->RegisterOverride("itkImageIOBase",
+                          "itkMincImageIO",
+                          "Minc Image IO",
+                          1,
+                          CreateObjectFunction<MincImageIO>::New());
+  }
+  
+  MincImageIOFactory::~MincImageIOFactory()
+  {
+  }
+  
+  const char*
+  MincImageIOFactory::GetITKSourceVersion(void) const
+  {
+    return ITK_SOURCE_VERSION;
+  }
+  
+  const char*
+  MincImageIOFactory::GetDescription() const
+  {
+    return "Minc ImageIO Factory, allows the loading of Minc images into insight";
+  }
+
+} // end namespace itk
+
new file mode 100644
--- /dev/null
+++ b/minc4itk/itkMincImageIOFactory.h
@@ -0,0 +1,71 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : 
+@DESCRIPTION: 
+@COPYRIGHT  :
+              Copyright 2006 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#ifndef __itkMincImageIOFactory_h
+#define __itkMincImageIOFactory_h
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4786 )
+#endif
+
+#include "itkObjectFactoryBase.h"
+#include "itkImageIOBase.h"
+
+namespace itk
+{
+/** \class MincImageIOFactory
+   * \brief Create instances of MincImageIO objects using an object factory.
+   */
+class ITK_EXPORT MincImageIOFactory : public ObjectFactoryBase
+{
+public:
+  /** Standard class typedefs. */
+  typedef MincImageIOFactory   Self;
+  typedef ObjectFactoryBase  Superclass;
+  typedef SmartPointer<Self>  Pointer;
+  typedef SmartPointer<const Self>  ConstPointer;
+
+  /** Class methods used to interface with the registered factories. */
+  virtual const char* GetITKSourceVersion(void) const;
+  virtual const char* GetDescription(void) const;
+
+  /** Method for class instantiation. */
+  itkFactorylessNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(MincImageIOFactory, ObjectFactoryBase);
+
+  /** Register one factory of this type  */
+  static void RegisterOneFactory(void)
+  {
+    MincImageIOFactory::Pointer metaFactory = MincImageIOFactory::New();
+    ObjectFactoryBase::RegisterFactory(metaFactory);
+  }
+
+protected:
+  MincImageIOFactory();
+  ~MincImageIOFactory();
+  virtual void PrintSelf(std::ostream& os, Indent indent) const;
+
+private:
+  MincImageIOFactory(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+};
+
+
+} // end namespace itk
+
+#endif
new file mode 100644
--- /dev/null
+++ b/minc4itk/minc4itk_plugin.cxx
@@ -0,0 +1,25 @@
+#include "itkMincImageIOFactory.h"
+
+#ifdef WIN32
+#define MyPlugin_EXPORT __declspec(dllexport)
+#else
+#define MyPlugin_EXPORT 
+#endif
+
+extern "C" {
+  MyPlugin_EXPORT itk::ObjectFactoryBase* itkLoad();
+} 
+
+/**
+ * Routine that is called when the shared library is loaded by
+ * itk::ObjectFactoryBase::LoadDynamicFactories().
+ *
+ * itkLoad() is C (not C++) function.
+ */
+
+itk::ObjectFactoryBase* itkLoad()
+{
+  static itk::MincImageIOFactory::Pointer f=itk::MincImageIOFactory::New();
+  return f;
+}
+
new file mode 100644
--- /dev/null
+++ b/minc4itk/minc_general_transform.h
@@ -0,0 +1,278 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : 
+@DESCRIPTION: 
+@COPYRIGHT  :
+              Copyright 2006 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#ifndef __MINC_GENERAL_TRANSFORM_H__
+#define __MINC_GENERAL_TRANSFORM_H__
+
+#include <itkObject.h>
+#include <itkPoint.h>
+#include <itkVector.h>
+#include <itkCovariantVector.h>
+#include <vnl/vnl_matrix_fixed.h>
+#include <vnl/vnl_vector_fixed.h>
+#include <vnl/vnl_det.h>
+#include <vnl/vnl_vector_fixed_ref.h>
+#include <vnl/vnl_vector.h>
+
+#include <itkTransform.h>
+#include <itkObjectFactory.h>
+
+//minc header
+#include <volume_io.h>
+
+namespace minc
+{
+  /** \class XfmTransform
+   * \brief ITK wrapper around Minc general transform functions.
+   *
+   * \ingroup Transforms
+   *
+   */
+  template < class TScalarType=double, unsigned int NInputDimensions=3,unsigned int NOutputDimensions=3> 
+   class XfmTransform : public itk::Transform < TScalarType, NInputDimensions, NOutputDimensions>
+  {
+  public:
+    /** Standard class typedefs. */
+    typedef XfmTransform  Self;
+    typedef typename itk::Transform < TScalarType, NInputDimensions, NOutputDimensions> Superclass;
+    typedef typename itk::SmartPointer< Self >   Pointer;
+    typedef typename itk::SmartPointer< const Self >  ConstPointer;
+    
+    
+    /** New method for creating an object using a factory. */
+    itkNewMacro(Self);
+  
+    /** Run-time type information (and related methods). */
+    itkTypeMacro( XfmTransform, itk::Transform );
+  
+    /** Dimension of the domain space. */
+    itkStaticConstMacro(InputSpaceDimension, unsigned int, NInputDimensions);
+    itkStaticConstMacro(OutputSpaceDimension, unsigned int, NOutputDimensions);
+    
+    /** Type of the input parameters. */
+    
+    typedef  double ScalarType;
+  
+    /** Type of the input parameters. */
+    typedef typename Superclass::ParametersType ParametersType;
+  
+    /** Type of the Jacobian matrix. */
+    typedef typename Superclass::JacobianType  JacobianType;
+  
+    /** Standard vector type for this class. */
+    typedef itk::Vector<TScalarType,
+                  itkGetStaticConstMacro(InputSpaceDimension)>  InputVectorType;
+    typedef itk::Vector<TScalarType,
+                  itkGetStaticConstMacro(OutputSpaceDimension)> OutputVectorType;
+    
+    /** Standard covariant vector type for this class */
+    typedef itk::CovariantVector<TScalarType,
+                            itkGetStaticConstMacro(InputSpaceDimension)>  InputCovariantVectorType;
+                            
+    typedef itk::CovariantVector<TScalarType,
+                            itkGetStaticConstMacro(OutputSpaceDimension)> OutputCovariantVectorType;
+    
+    /** Standard coordinate point type for this class */
+    typedef itk::Point<TScalarType,NInputDimensions > InputPointType;
+  
+    typedef itk::Point<TScalarType,NInputDimensions > OutputPointType;
+    
+    /**  Method to transform a point. */
+    virtual OutputPointType TransformPoint(const InputPointType  &point ) const
+    {
+      if(!_initialized) return point;
+      if(_invert && !_initialized_invert)  return point;
+      OutputPointType pnt;
+      if(NInputDimensions==3 && NOutputDimensions==3)
+	general_transform_point((_invert ? &_xfm_inv : &_xfm), point[0], point[1], point[2],&pnt[0], &pnt[1], &pnt[2]);
+      else
+	itkExceptionMacro(<< "Sorry, only 3D to 3d minc xfm transform is currently implemented");
+      return pnt;
+    }
+    //! use finate element difference to estimate local jacobian 
+    void estimate_local_jacobian(const InputPointType  &orig, vnl_matrix_fixed< double, 3, 3 > &m)
+    {
+      double u1,v1,w1;
+      double u2,v2,w2;
+      const double delta=1e-4;
+
+      general_transform_point((_invert ? &_xfm_inv : &_xfm) , orig[0]-delta, orig[1], orig[2],&u1, &v1, &w1);
+      general_transform_point((_invert ? &_xfm_inv : &_xfm) , orig[0]+delta, orig[1], orig[2],&u2, &v2, &w2);
+      m(0,0)=(u2-u1)/(2*delta);
+      m(0,1)=(v2-v1)/(2*delta);
+      m(0,2)=(w2-w1)/(2*delta);
+      
+      general_transform_point((_invert ? &_xfm_inv : &_xfm) , orig[0], orig[1]-delta, orig[2],&u1, &v1, &w1);
+      general_transform_point((_invert ? &_xfm_inv : &_xfm) , orig[0], orig[1]+delta, orig[2],&u2, &v2, &w2);
+      m(1,0)=(u2-u1)/(2*delta);
+      m(1,1)=(v2-v1)/(2*delta);
+      m(1,2)=(w2-w1)/(2*delta);
+      
+      general_transform_point((_invert ? &_xfm_inv : &_xfm), orig[0], orig[1], orig[2]-delta,&u1, &v1, &w1);
+      general_transform_point((_invert ? &_xfm_inv : &_xfm), orig[0], orig[1], orig[2]+delta,&u2, &v2, &w2);
+      m(2,0)=(u2-u1)/(2*delta);
+      m(2,1)=(v2-v1)/(2*delta);
+      m(2,2)=(w2-w1)/(2*delta);
+    }
+    
+    /**  Method to transform a vector. */
+    virtual OutputVectorType TransformVector(const InputVectorType &vector) const 
+    {
+      itkExceptionMacro( << "Not Implemented" );
+      return vector; 
+    }
+  
+    /**  Method to transform a vnl_vector. */
+/*    virtual OutputVnlVectorType TransformVector(const InputVnlVectorType &vector) const
+    {
+      itkExceptionMacro( << "Not Implemented" );
+      return vector; 
+    }*/
+  
+    
+    /**  Method to transform a CovariantVector. */
+    virtual OutputCovariantVectorType TransformCovariantVector(
+      const InputCovariantVectorType &vector) const
+    {
+      itkExceptionMacro( << "Not Implemented" );
+      return vector; 
+    }
+
+    
+    /** Set the transformation to an Identity
+     */
+    virtual void SetIdentity( void )
+    {
+      _cleanup();
+    }
+    
+#if ( ITK_VERSION_MAJOR > 3 ) 
+    virtual void SetFixedParameters(const ParametersType &)
+    {
+      itkExceptionMacro( << "Not Implemented" );
+    }
+    
+    virtual void ComputeJacobianWithRespectToParameters(
+                const InputPointType &,
+                JacobianType &) const
+    {
+      itkExceptionMacro( << "Not Implemented" );
+    }
+    
+   virtual void ComputeJacobianWithRespectToPosition(
+                const InputPointType & x,
+                JacobianType &jacobian ) const
+    {
+      itkExceptionMacro( << "Not Implemented" );
+    }
+    
+#endif
+
+    
+#if ( ITK_VERSION_MAJOR > 3 ) 
+    virtual NumberOfParametersType GetNumberOfParameters(void) const
+#else
+    virtual unsigned int GetNumberOfParameters(void) const
+#endif
+    {
+      //this transform is defined by XFM file
+      itkExceptionMacro( << "Not Defined" );
+      return 0;
+    }
+    
+    /** Set the Transformation Parameters
+     * and update the internal transformation. */
+    virtual void  SetParameters(const ParametersType & param)
+    {
+      itkExceptionMacro( << "Not Implemented" );
+    }
+    
+    virtual const ParametersType & GetParameters(void)
+    {
+      itkExceptionMacro( << "Not Implemented" );
+      return _parameters;
+    }
+    
+#if ( ITK_VERSION_MAJOR == 3 ) 
+    virtual const JacobianType & GetJacobian(const InputPointType  & point) const
+    { 
+      itkExceptionMacro( << "Not Implemented" );
+      return this->m_Jacobian;
+    }
+#endif    
+    
+    void OpenXfm(const char *xfm)
+    {
+      _cleanup();
+      if(input_transform_file((char*)xfm, &_xfm)!=OK)
+        itkExceptionMacro( << "Error reading XFM:" << xfm );
+      _initialized=true;
+    }
+    
+    void Invert(void)
+    {
+      if(!_initialized)
+        itkExceptionMacro( << "XFM not initialized" );
+      if(!_initialized_invert)
+      {
+        create_inverse_general_transform(&_xfm,&_xfm_inv);
+        _initialized_invert=true;
+      }
+      _invert= !_invert;
+    }
+    
+  protected:
+    
+#if ( ITK_VERSION_MAJOR > 3 ) 
+    XfmTransform(): itk::Transform< TScalarType, NInputDimensions, NOutputDimensions>(0),_invert(false),_initialized(false),_initialized_invert(false)
+    { 
+    }
+#else  
+    XfmTransform(): itk::Transform< TScalarType, NInputDimensions, NOutputDimensions>(NInputDimensions,NOutputDimensions),_invert(false),_initialized(false),_initialized_invert(false)
+    { 
+    }
+#endif  
+    
+    virtual ~XfmTransform() 
+    {
+      _cleanup();
+    }
+      
+    void _cleanup(void)
+    {
+      if(_initialized)
+      {
+        delete_general_transform(&_xfm);
+      }
+      if(_initialized_invert)
+      {
+        delete_general_transform(&_xfm_inv);
+      }
+      _initialized=false;
+      _initialized_invert=false;
+    }
+    
+    ParametersType _parameters;
+    mutable General_transform _xfm,_xfm_inv;//quick fix for general_transform
+    bool _invert;
+    bool _initialized,_initialized_invert;
+    
+  private:
+    XfmTransform ( const Self & ); //purposely not implemented
+    void operator= ( const Self & ); //purposely not implemented
+  };
+
+  
+};
+#endif //__MINC_GENERAL_TRANSFORM_H__
new file mode 100644
--- /dev/null
+++ b/minc4itk/minc_helpers.cxx
@@ -0,0 +1,778 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : 
+@DESCRIPTION: 
+@COPYRIGHT  :
+              Copyright 2006 Vladimir Fonov, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+#include <math.h>
+#include "minc_helpers.h"
+
+#include <itkMetaDataObject.h>
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <iterator>
+
+using namespace std;
+
+namespace minc
+{
+	int get_image_limits (image3d::Pointer img, voxel_type &min,voxel_type &max)
+	{
+		//1. get min, max
+		minc::image3d_iterator it (img, img->GetLargestPossibleRegion ());
+		int count = 0;
+	
+		min = std::numeric_limits < voxel_type >::max ();
+		  
+		max = -std::numeric_limits < voxel_type >::max ();
+		for (it.GoToBegin (); !it.IsAtEnd (); ++it)
+		{
+			voxel_type v=it.Value ();
+			if (fabs(double(v)) > 1e20)
+			  continue;
+			count++;
+			if (v < min)
+			  min = v;
+			if (v > max)
+			  max = v;
+		}
+		return count;
+	}
+  
+	int get_image_limits (mask3d::Pointer img, voxel_type &min,voxel_type &max)
+	{
+		//1. get min, max
+		minc::mask3d_iterator it (img, img->GetLargestPossibleRegion ());
+		int count = 0;
+	
+		min = std::numeric_limits < voxel_type >::max ();
+		  
+		max = -std::numeric_limits < voxel_type >::max ();
+		for (it.GoToBegin (); !it.IsAtEnd (); ++it)
+		{
+			voxel_type v=it.Value ();
+			if (fabs(double(v)) > 1e20)
+			  continue;
+			count++;
+			if (v < min)
+			  min = v;
+			if (v > max)
+			  max = v;
+		}
+		return count;
+	}
+	
+	int get_image_limits (def3d::Pointer img, voxel_type &min, voxel_type &max)
+	{
+		//1. get min, max
+		minc::def3d_iterator it (img, img->GetLargestPossibleRegion ());
+		int count = 0;
+	
+		min = std::numeric_limits < voxel_type >::max ();
+		max = -std::numeric_limits < voxel_type >::max ();
+		
+		for (it.GoToBegin (); !it.IsAtEnd (); ++it)
+		{
+			voxel_type va=v_max(it.Value () );
+			voxel_type vi=v_min(it.Value () );
+			if (fabs(double(va)) > 1e20)
+			  continue;
+			count++;
+			if (vi < min)
+			  min = vi;
+			if (va > max)
+			  max = va;
+		}
+		return count;
+	}
+  
+  void normalize_mask(mask3d::Pointer img)
+  {
+		minc::mask3d_iterator it (img, img->GetLargestPossibleRegion ());
+		for (it.GoToBegin (); !it.IsAtEnd (); ++it)
+		{
+			if(it.Value ()) it.Value ()=1;
+		}
+  }
+	
+	void write_tags(const tag_points& tags, const char * file)
+	{
+		std::ofstream out(file);
+		if(!out.good()) REPORT_ERROR("Can't open file!");
+		out<<"MNI Tag Point File"<<std::endl;
+		out<<"Volumes = 1;"<<std::endl<<std::endl;
+		out<<"Points =";
+		//TODO add all the things
+		for(tag_points::const_iterator i=tags.begin();i!=tags.end();i++)
+		{
+			out<<std::endl<<(*i)[0]<<" "<<(*i)[1]<< " "<<(*i)[2] <<" \"\"";
+			if(!out.good()) REPORT_ERROR("Can't write to file!");
+		}
+		out << ";" << std::endl;
+	}
+  
+	void write_tags(const tag_points& tags,const std::vector<int>& labels, const char * file)
+	{
+		std::ofstream out(file);
+		if(!out.good()) REPORT_ERROR("Can't open file!");
+		out<<"MNI Tag Point File"<<std::endl;
+		out<<"Volumes = 1;"<<std::endl<<std::endl;
+		out<<"Points =";
+		//TODO add all the things
+    std::vector<int>::const_iterator j;
+    tag_points::const_iterator i;
+		for(i=tags.begin(),j=labels.begin();i!=tags.end()&&j!=labels.end();i++,j++)
+		{
+			out<<std::endl<<(*i)[0]<<" "<<(*i)[1]<< " "<<(*i)[2] <<" \""<<*j<<"\"";
+			if(!out.good()) REPORT_ERROR("Can't write to file!");
+		}
+		out << ";" << std::endl;
+	}
+  
+  void write_tags(const tag_points& tags,const std::vector<float>& values, const char * file)
+  {
+		std::ofstream out(file);
+		if(!out.good()) REPORT_ERROR("Can't open file!");
+		out<<"MNI Tag Point File"<<std::endl;
+		out<<"Volumes = 1;"<<std::endl<<std::endl;
+		out<<"Points =";
+		//TODO add all the things
+    std::vector<float>::const_iterator j;
+    tag_points::const_iterator i;
+		for(i=tags.begin(),j=values.begin();i!=tags.end()&&j!=values.end();i++,j++)
+		{
+			out<<std::endl<<(*i)[0]<<" "<<(*i)[1]<< " "<<(*i)[2] <<" \""<<*j<<"\"";
+			if(!out.good()) REPORT_ERROR("Can't write to file!");
+		}
+		out << ";" << std::endl;
+    
+  }
+  
+  void write_tags(const tag_points& tags,const std::vector<double>& values, const char * file)
+  {
+    std::ofstream out(file);
+    if(!out.good()) REPORT_ERROR("Can't open file!");
+    out<<"MNI Tag Point File"<<std::endl;
+    out<<"Volumes = 1;"<<std::endl<<std::endl;
+    out<<"Points =";
+		//TODO add all the things
+    std::vector<double>::const_iterator j;
+    tag_points::const_iterator i;
+    for(i=tags.begin(),j=values.begin();i!=tags.end()&&j!=values.end();i++,j++)
+    {
+      out<<std::endl<<(*i)[0]<<" "<<(*i)[1]<< " "<<(*i)[2] <<" \""<<*j<<"\"";
+      if(!out.good()) REPORT_ERROR("Can't write to file!");
+    }
+    out << ";" << std::endl;
+    
+  }
+	
+  void write_2tags(const tag_points& tags,const tag_points& tags2, const char * file)
+	{
+		if(tags.size()!=tags2.size()) 
+			REPORT_ERROR("Mismatching number of tags!");
+		
+		std::ofstream out(file);
+		if(!out.good()) REPORT_ERROR("Can't open file!");
+		out<<"MNI Tag Point File"<<std::endl;
+		out<<"Volumes = 2;"<<std::endl<<std::endl;
+		out<<"Points =";
+		//TODO add all the things
+		tag_points::const_iterator j=tags2.begin();
+		tag_points::const_iterator i=tags.begin();
+		for(;i!=tags.end();i++,j++)
+		{
+			out<<std::endl<<(*i)[0]<<" "<<(*i)[1]<< " "<<(*i)[2]<<" "<<(*j)[0]<<" "<<(*j)[1]<< " "<<(*j)[2] <<" \"\"";
+			if(!out.good()) REPORT_ERROR("Can't write to file!");
+		}
+		out << ";" << std::endl;
+	}
+  
+  static void split_string(char *str,std::vector<std::string>& lst,const char *delim=" ")
+  {
+    lst.clear();
+    char *str2, *token;
+    char *saveptr;
+    while(str2=strtok_r(str,delim,&saveptr))
+    {
+      str=NULL;
+      lst.push_back(str2);
+    }
+  }
+	
+	void read_tags(tag_points& tags, const char * file,int vol)
+	{
+		ifstream in(file);
+		if(!in.good()) REPORT_ERROR("Can't open file!");
+		//tags.clear();
+		bool seen_points=false;
+		const int _buffer_len=4095;
+		char tmp[_buffer_len+1];
+    int _vol=vol;
+    
+		while(!in.eof() )
+		{
+			in.getline(tmp,_buffer_len,'\n');
+      if(tmp[0]=='%') continue;
+			if(!in.good()) break;
+			if(!seen_points) 
+			{
+        if(!strncmp(tmp,"Volumes =",9)) //got number of volumes 
+        {
+          char *del=strchr(tmp+9,';');
+          if(del) *del=0;
+          _vol=atoi(tmp+9);
+          if(_vol<0 || _vol>2) _vol=1;
+
+        }
+        
+				if(!strcmp(tmp,"Points =")) //found
+				{
+					seen_points=true;
+					continue;
+				}
+			} else {
+				std::istringstream str (std::string((const char *)tmp));
+				tag_point tag;
+				double dummy;
+        
+				if(_vol>1 && vol>1) //skip extra values
+					str >> dummy >> dummy >> dummy;
+        
+				str>>tag[0]>>tag[1]>>tag[2];
+				tags.push_back(tag);
+			}
+		}
+	}
+  
+	void read_tags(tag_points& tags, std::vector<int>& labels, const char * file, int vol)
+	{
+		ifstream in(file);
+		if(!in.good()) REPORT_ERROR("Can't open file!");
+		//tags.clear();
+		bool seen_points=false;
+		const int _buffer_len=4095;
+		char tmp[_buffer_len+1];
+    int _vol=vol;
+    
+		while(!in.eof() )
+		{
+			in.getline(tmp,_buffer_len,'\n');
+			if(!in.good()) break;
+      if(tmp[0]=='%') continue;
+      
+			if(!seen_points) 
+			{
+        if(!strncmp(tmp,"Volumes =",9)) //got number of volumes 
+        {
+          char *del=strchr(tmp+9,';');
+          if(del) *del=0;
+          _vol=atoi(tmp+9);
+          if(_vol<0 || _vol>2) _vol=1;
+        }
+        if(!strcmp(tmp,"Points =")) //found
+				{
+					seen_points=true;
+					continue;
+				}
+			} else {
+        std::vector<std::string> lst;
+        tag_point tag;
+
+        split_string(tmp,lst," ");
+        int skip=0;
+        
+        if(lst.size()<3) continue;
+        
+        if(vol==2 && _vol==2 && lst.size()>5) //skip extra values
+          skip=3;
+        
+        tag[0]=atof(lst[skip].c_str());
+        tag[1]=atof(lst[skip+1].c_str());
+        tag[2]=atof(lst[skip+2].c_str());
+        
+				tags.push_back(tag);
+        
+        if((lst.size()>6&&_vol==2) || lst.size()>3)
+        {
+          std::string lb=lst[lst.size()-1];
+          
+          //Analyze label
+          std::string::size_type first=lb.find('"');
+          std::string::size_type last=lb.rfind('"');
+          if( first==std::string::npos || last==std::string::npos )
+            labels.push_back(0);
+          else
+            labels.push_back(atoi(lb.substr(first+1,last-first).c_str()));
+        } else 
+          labels.push_back(0);
+			}
+		}
+	}
+  
+  void read_tags(tag_points& tags, std::vector<double>& labels, const char * file, int vol)
+  {
+    ifstream in(file);
+    if(!in.good()) REPORT_ERROR("Can't open file!");
+		//tags.clear();
+    bool seen_points=false;
+    const int _buffer_len=4095;
+    char tmp[_buffer_len+1];
+    int _vol=vol;
+    
+    while(!in.eof() )
+    {
+      in.getline(tmp,_buffer_len,'\n');
+      if(!in.good()) break;
+      if(tmp[0]=='%') continue;
+      
+      if(!seen_points) 
+      {
+        if(!strncmp(tmp,"Volumes =",9)) //got number of volumes 
+        {
+          char *del=strchr(tmp+9,';');
+          if(del) *del=0;
+          _vol=atoi(tmp+9);
+          if(_vol<0 || _vol>2) _vol=1;
+        }
+        if(!strcmp(tmp,"Points =")) //found
+        {
+          seen_points=true;
+          continue;
+        }
+      } else {
+        std::vector<std::string> lst;
+        tag_point tag;
+
+        split_string(tmp,lst," ");
+        int skip=0;
+        
+        if(lst.size()<3) continue;
+        
+        if(vol==2 && _vol==2 && lst.size()>5) //skip extra values
+          skip=3;
+        
+        tag[0]=atof(lst[skip].c_str());
+        tag[1]=atof(lst[skip+1].c_str());
+        tag[2]=atof(lst[skip+2].c_str());
+        
+        tags.push_back(tag);
+        if((lst.size()>6&&_vol==2) || lst.size()>3)
+        {
+          std::string lb=lst[lst.size()-1];
+          
+          std::string::size_type first=lb.find('"');
+          std::string::size_type last=lb.rfind('"');
+          if( first==std::string::npos || last==std::string::npos )
+            labels.push_back(0);
+          else
+            labels.push_back(atof(lb.substr(first+1,last-first).c_str()));
+        } else 
+           labels.push_back(0);
+      }
+    }
+  }
+  
+  void read_tags(tag_points& tags, std::vector<float>& labels, const char * file, int vol)
+  {
+    ifstream in(file);
+    if(!in.good()) REPORT_ERROR("Can't open file!");
+		//tags.clear();
+    bool seen_points=false;
+    const int _buffer_len=4095;
+    char tmp[_buffer_len+1];
+    int _vol=vol;
+    
+    while(!in.eof() )
+    {
+      in.getline(tmp,_buffer_len,'\n');
+      if(!in.good()) break;
+      if(tmp[0]=='%') continue;
+      
+      if(!seen_points) 
+      {
+        if(!strncmp(tmp,"Volumes =",9)) //got number of volumes 
+        {
+          char *del=strchr(tmp+9,';');
+          if(del) *del=0;
+          _vol=atoi(tmp+9);
+          if(_vol<0 || _vol>2) _vol=1;
+        }
+        if(!strcmp(tmp,"Points =")) //found
+        {
+          seen_points=true;
+          continue;
+        }
+      } else {
+        std::vector<std::string> lst;
+        tag_point tag;
+
+        split_string(tmp,lst," ");
+        int skip=0;
+        
+        if(lst.size()<3) continue;
+        
+        if(vol==2 && _vol==2 && lst.size()>5) //skip extra values
+          skip=3;
+        
+        tag[0]=atof(lst[skip].c_str());
+        tag[1]=atof(lst[skip+1].c_str());
+        tag[2]=atof(lst[skip+2].c_str());
+        
+        tags.push_back(tag);
+        if((lst.size()>6&&_vol==2) || lst.size()>3)
+        {
+          std::string lb=lst[lst.size()-1];
+          
+          std::string::size_type first=lb.find('"');
+          std::string::size_type last=lb.rfind('"');
+          if( first==std::string::npos || last==std::string::npos )
+            labels.push_back(0);
+          else
+            labels.push_back(atof(lb.substr(first+1,last-first).c_str()));
+        } else 
+          labels.push_back(0);
+      }
+    }
+  }
+  
+  void read_tags(tag_points& tag1, tag_points& tag2,std::vector<double>& labels, const char * file)
+  {
+    ifstream in(file);
+    if(!in.good()) REPORT_ERROR("Can't open file!");
+    //tags.clear();
+    bool seen_points=false;
+    const int _buffer_len=4095;
+    char tmp[_buffer_len+1];
+    int _vol=2;
+    
+    while(!in.eof() )
+    {
+      in.getline(tmp,_buffer_len,'\n');
+      if(!in.good()) break;
+      if(tmp[0]=='%') continue;
+      
+      if(!seen_points) 
+      {
+        if(!strncmp(tmp,"Volumes =",9)) //got number of volumes 
+        {
+          char *del=strchr(tmp+9,';');
+          if(del) *del=0;
+          _vol=atoi(tmp+9);
+          if(_vol<0 || _vol>2) _vol=1;
+        }
+        if(!strcmp(tmp,"Points =")) //found
+        {
+          seen_points=true;
+          continue;
+        }
+      } else {
+        std::vector<std::string> lst;
+        tag_point tag;
+
+        split_string(tmp,lst," ");
+        int skip=0;
+        
+        if(lst.size()<3) continue;
+        
+        tag[0]=atof(lst[0].c_str());
+        tag[1]=atof(lst[1].c_str());
+        tag[2]=atof(lst[2].c_str());
+        tag1.push_back(tag);
+        
+        if(lst.size()>5 && _vol==2)
+        {
+          tag[0]=atof(lst[0].c_str());
+          tag[1]=atof(lst[1].c_str());
+          tag[2]=atof(lst[2].c_str());
+        } else {
+          tag[0]=0;
+          tag[1]=0;
+          tag[2]=0;
+        }
+        tag2.push_back(tag);
+        
+        if((lst.size()>6&&_vol==2) || lst.size()>3)
+        {
+          std::string lb=lst[lst.size()-1];
+          std::string::size_type first=lb.find('"');
+          std::string::size_type last=lb.rfind('"');
+          if( first==std::string::npos || last==std::string::npos )
+            labels.push_back(0);
+          else
+            labels.push_back(atof(lb.substr(first+1,last-first).c_str()));
+        } else 
+          labels.push_back(0);
+      }
+    }
+  }
+  
+
+  void load_parameters(const char *file,itk::Array<double> &param)
+  {
+    std::vector<double> p;
+    ifstream in(file);
+    if(!in.good()) 
+      REPORT_ERROR("Can't open the file for reading!");
+    copy(istream_iterator<double>(in), istream_iterator<double>(), back_inserter(p));
+    if(p.empty()) // probably this is not right!
+      REPORT_ERROR("Can't read parameters!");
+    param.SetSize(p.size());
+    for(int i=0;i<p.size();i++)
+      param[i]=p[i];
+  }
+  
+  void load_parameters(const char *file,itk::Array<double> &param,int n)
+  {
+    std::vector<double> p;
+    ifstream in(file);
+    if(!in.good()) 
+      REPORT_ERROR("Can't open the file for reading!");
+    copy(istream_iterator<double>(in), istream_iterator<double>(), back_inserter(p));
+    if(p.empty()) // probably this is not right!
+      REPORT_ERROR("Can't read parameters!");
+    param.SetSize(n);
+    param.Fill(0);
+    
+    for(int i=0;i<p.size() && i<n;i++)
+      param[i]=p[i];
+  }
+
+  void save_parameters(const char *file,const itk::Array<double> &param)
+  {
+    std::vector<double> p;
+    ofstream out(file);
+    if(!out.good())
+      REPORT_ERROR("Can't open the file for writing!");
+    out.precision(40);
+    for(int i=0;i<param.Size();i++)
+      out<<param[i]<<endl;
+  }
+  
+  //simplistic XFM file parsing
+  void read_linear_xfm(const char *xfm,itk::Matrix<double,3,3>& rot, itk::Vector<double,3>& tran )
+  {
+    rot.SetIdentity();
+    tran.Fill(0);
+    std::ifstream in(xfm);
+    char tmp[1024];
+    bool found_transform=false;
+    while(!in.eof() && in.good())
+    {
+      in.getline(tmp,1023);
+      if(strstr(tmp,"Linear_Transform =")) // ok, found the description
+      { 
+          found_transform=true;
+          break;
+      }
+    }
+    if(found_transform)
+    {
+      for(int c=0;c<3;c++)
+      {
+        in>>rot[c][0]
+          >>rot[c][1]
+          >>rot[c][2]
+          >>tran[c];
+      }
+    }
+  }
+  
+  void read_linear_xfm(const char *xfm,itk::Matrix<double,2,2>& rot, itk::Vector<double,2>& tran )
+  {
+    itk::Matrix<double,3,3> r;
+    itk::Vector<double,3> t;
+    read_linear_xfm(xfm,r,t);
+    
+    for(int i=0;i<2;i++)
+    {
+      for(int j=0;j<2;j++)
+      {
+        rot[i][j]=r[i][j];
+      }
+      tran[i]=t[i];
+    }
+  }
+
+
+  void write_linear_xfm(const char *xfm,const itk::Matrix<double,3,3>& rot,const itk::Vector<double,3>& tran )
+  {
+      std::ofstream out(xfm);
+      out.precision(10);
+      out<<"MNI Transform File"<<std::endl;
+      out<<"Transform_Type = Linear;"<<std::endl<<"Linear_Transform =";
+      for(int c=0;c<3;c++)
+      {
+        out<<std::endl<<rot[c][0]<<" "
+                      <<rot[c][1]<<" "
+                      <<rot[c][2]<<" "
+                      <<tran[c];
+      }
+      out<<";"<<std::endl;
+  }
+  
+  void write_linear_xfm(const char *xfm,const itk::Matrix<double,2,2>& rot,const itk::Vector<double,2>& tran )
+  {
+    std::ofstream out(xfm);
+    out.precision(10);
+    out<<"MNI Transform File"<<std::endl;
+    out<<"Transform_Type = Linear;"<<std::endl<<"Linear_Transform =";
+    for(int c=0;c<2;c++)
+    {
+      out<<std::endl<<rot[c][0]<<" "
+          <<rot[c][1]<<" "
+          <<0<<" "
+          <<tran[c];
+    }
+
+    out<<std::endl<<0<<" "
+        <<0<<" "
+        <<0<<" "
+        <<0;
+
+    out<<";"<<std::endl;
+  }
+
+  
+  void write_combined_xfm(const char *xfm,const itk::Matrix<double,3,3>& rot,const itk::Vector<double,3>& tran, const char *grid )
+  {
+    std::ofstream out(xfm);
+    out.precision(10);
+    out<<"MNI Transform File"<<std::endl;
+    out<<"Transform_Type = Linear;"<<std::endl<<"Linear_Transform =";
+    for(int c=0;c<3;c++)
+    {
+      out<<std::endl<<rot[c][0]<<" "
+          <<rot[c][1]<<" "
+          <<rot[c][2]<<" "
+          <<tran[c];
+    }
+    out<<";"<<std::endl;
+    
+    out<<"Transform_Type = Grid_Transform;"<<std::endl<<"Displacement_Volume = "<<grid<<";"<<std::endl;
+  }
+  
+  void write_combined_xfm(const char *xfm,const itk::Matrix<double,2,2>& rot,const itk::Vector<double,2>& tran, const char *grid )
+  {
+    std::ofstream out(xfm);
+    out.precision(10);
+    out<<"MNI Transform File"<<std::endl;
+    out<<"Transform_Type = Linear;"<<std::endl<<"Linear_Transform =";
+    for(int c=0;c<2;c++)
+    {
+      out<<std::endl<<rot[c][0]<<" "
+          <<rot[c][1]<<" "
+          <<0<<" "
+          <<tran[c];
+    }
+
+    out<<std::endl<<0<<" "
+        <<0<<" "
+        <<0<<" "
+        <<0;
+
+    out<<";"<<std::endl;
+    
+    out<<"Transform_Type = Grid_Transform;"<<std::endl<<"Displacement_Volume = "<<grid<<";"<<std::endl;
+    
+  }
+  
+  void write_combined_xfm(const char *xfm, const char *grid,const itk::Matrix<double,3,3>& rot,const itk::Vector<double,3>& tran)
+  {
+    std::ofstream out(xfm);
+    out.precision(10);
+    out<<"MNI Transform File"<<std::endl;
+    
+    out<<"Transform_Type = Grid_Transform;"<<std::endl<<"Displacement_Volume = "<<grid<<";"<<std::endl;
+    
+    out<<"Transform_Type = Linear;"<<std::endl<<"Linear_Transform =";
+    for(int c=0;c<3;c++)
+    {
+      out<<std::endl<<rot[c][0]<<" "
+          <<rot[c][1]<<" "
+          <<rot[c][2]<<" "
+          <<tran[c];
+    }
+    out<<";"<<std::endl;
+  }
+  
+  void write_combined_xfm(const char *xfm, const char *grid,const itk::Matrix<double,2,2>& rot,const itk::Vector<double,2>& tran )
+  {
+    std::ofstream out(xfm);
+    out.precision(10);
+    out<<"MNI Transform File"<<std::endl;
+    
+    out<<"Transform_Type = Grid_Transform;"<<std::endl<<"Displacement_Volume = "<<grid<<";"<<std::endl;
+    
+    out<<"Transform_Type = Linear;"<<std::endl<<"Linear_Transform =";
+    for(int c=0;c<2;c++)
+    {
+      out<<std::endl<<rot[c][0]<<" "
+          <<rot[c][1]<<" "
+          <<0<<" "
+          <<tran[c];
+    }
+
+    out<<std::endl<<0<<" "
+        <<0<<" "
+        <<0<<" "
+        <<0;
+
+    out<<";"<<std::endl;
+  }
+  
+  void write_nonlinear_xfm(const char *xfm,const char *grid)
+  {
+    std::ofstream out(xfm);
+    out<<"MNI Transform File"<<std::endl;
+    out<<"Transform_Type = Linear;"<<std::endl<<"Linear_Transform =";
+    for(int c=0;c<3;c++)
+    {
+      out<<std::endl<<(c==0?1:0)<<" " <<(c==1?1:0)<<" " <<(c==2?1:0)<<" " <<0;
+    }
+    out<<";"<<std::endl;
+    
+    out<<"Transform_Type = Grid_Transform;"<<std::endl<<" Displacement_Volume = "<<grid<<";"<<std::endl;
+  }
+  
+  void set_minc_storage_type(itk::Object* image,nc_type datatype,bool is_signed)
+  {
+    itk::EncapsulateMetaData( image->GetMetaDataDictionary(),"datatype",datatype);
+    itk::EncapsulateMetaData( image->GetMetaDataDictionary(),"signed",is_signed);
+  }
+  
+  void copy_metadata(itk::Object* dst,itk::Object* src)
+  {
+    dst->SetMetaDataDictionary(src->GetMetaDataDictionary());
+  }
+  
+  void copy_dimorder(itk::Object* dst,itk::Object* src)
+  {
+    std::vector<std::string> dimorder;
+    if(itk::ExposeMetaData(src->GetMetaDataDictionary(),"dimorder",dimorder))
+    {
+      itk::EncapsulateMetaData(dst->GetMetaDataDictionary(),"dimorder",dimorder);
+    }
+  }
+  
+  void append_history(itk::Object* dst,const std::string& history)
+  {
+    std::string old_history;
+    itk::ExposeMetaData<std::string>( dst->GetMetaDataDictionary() , "history",old_history);
+    old_history+=history;
+    itk::EncapsulateMetaData( dst->GetMetaDataDictionary(),"history",old_history);
+  }
+
+  
+};//minc
+
new file mode 100644
--- /dev/null
+++ b/minc4itk/minc_helpers.h
@@ -0,0 +1,384 @@
+#ifndef _MINC_HELPERS_H_
+#define _MINC_HELPERS_H_
+
+#include <complex>
+#include <vector>
+#include <algorithm>
+
+#include <itkArray.h>
+
+#if ( ITK_VERSION_MAJOR > 3 ) 
+#include <itkImage.h>
+#else
+#include <itkOrientedImage.h>
+#endif 
+
+#include <itkImageRegionIteratorWithIndex.h>
+#include <itkImageRegionConstIteratorWithIndex.h>
+
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+#include <itkImageIOFactory.h>
+
+#include "itkMincImageIOFactory.h"
+#include "itkMincImageIO.h"
+#include <minc_io_fixed_vector.h>
+
+namespace minc
+{
+  
+  typedef unsigned char minc_mask_voxel;
+  
+	typedef float voxel_type;
+	const int volume_dimensions = 3;
+  
+  typedef itk::Vector<float,volume_dimensions>    def_vector;
+  typedef itk::Point<double,volume_dimensions>    tag_point;
+  typedef std::vector<tag_point>  tag_points;
+	typedef std::complex < voxel_type > complex;
+
+#if ( ITK_VERSION_MAJOR > 3 ) 
+	typedef itk::Image < complex, volume_dimensions > image3d_complex;
+	typedef itk::Image < voxel_type, volume_dimensions > image3d;
+	typedef itk::Image < minc_mask_voxel, volume_dimensions > mask3d;
+	typedef itk::Image < def_vector, volume_dimensions > def3d;
+#else
+	typedef itk::OrientedImage < complex, volume_dimensions > image3d_complex;
+	typedef itk::OrientedImage < voxel_type, volume_dimensions > image3d;
+	typedef itk::OrientedImage < minc_mask_voxel, volume_dimensions > mask3d;
+	typedef itk::OrientedImage < def_vector, volume_dimensions > def3d;
+#endif
+
+  
+	
+	typedef itk::ImageRegionIteratorWithIndex < image3d > image3d_iterator;
+	typedef itk::ImageRegionConstIteratorWithIndex < image3d > image3d_const_iterator;
+	
+	typedef itk::ImageRegionIteratorWithIndex < mask3d > mask3d_iterator;
+	typedef itk::ImageRegionConstIteratorWithIndex < mask3d > mask3d_const_iterator;
+	
+	typedef itk::ImageRegionIteratorWithIndex < def3d > def3d_iterator;
+	typedef itk::ImageRegionConstIteratorWithIndex < def3d > def3d_const_iterator;
+	
+	typedef itk::ImageRegionIteratorWithIndex < image3d_complex > image3d_complex_iterator;
+	typedef itk::ImageRegionConstIteratorWithIndex < image3d_complex > image3d_complex_const_iterator;
+
+  //! find a maximum of elements
+  template<class T> float v_max(const T& c)
+  {
+    float s=std::numeric_limits < float >::min ();;
+    for(unsigned int i=0;i<3;i++)
+      if(c[i]>s) s=c[i];
+    return s;
+  }
+
+  //! find a minimum of elements
+  template<class T> float v_min(const T& c) 
+  {
+    float s=std::numeric_limits < float >::max ();;
+    for(unsigned int i=0;i<3;i++)
+      if(c[i]<s) s=c[i];
+    return s;
+  }
+
+  //! allocate volume of the same dimension,spacing and origin
+  template<class T,class S> void allocate_same(typename T::Pointer &image,const typename S::Pointer &sample)
+  {
+		image->SetLargestPossibleRegion(sample->GetLargestPossibleRegion());
+		image->SetBufferedRegion(sample->GetLargestPossibleRegion());
+		image->SetRequestedRegion(sample->GetLargestPossibleRegion());
+		image->SetSpacing( sample->GetSpacing() );
+		image->SetOrigin ( sample->GetOrigin() );
+    image->SetDirection(sample->GetDirection());
+		image->Allocate();
+  }
+  
+  //! allocate volume of the same dimension,spacing and origin
+  template<class T,class S> void allocate_same(typename T::Pointer &image,const typename S::ConstPointer &sample)
+  {
+    image->SetLargestPossibleRegion(sample->GetLargestPossibleRegion());
+    image->SetBufferedRegion(sample->GetLargestPossibleRegion());
+    image->SetRequestedRegion(sample->GetLargestPossibleRegion());
+    image->SetSpacing( sample->GetSpacing() );
+    image->SetOrigin ( sample->GetOrigin() );
+    image->SetDirection(sample->GetDirection());
+    image->Allocate();
+  }
+  
+  
+  
+  //! allocate volume of the same dimension,spacing and origin
+  template<class T,class S> typename T::Pointer allocate_same(const typename S::Pointer &sample)
+  {
+    typename T::Pointer image=T::New();
+    image->SetLargestPossibleRegion(sample->GetLargestPossibleRegion());
+    image->SetBufferedRegion(sample->GetLargestPossibleRegion());
+    image->SetRequestedRegion(sample->GetLargestPossibleRegion());
+    image->SetSpacing( sample->GetSpacing() );
+    image->SetOrigin ( sample->GetOrigin() );
+    image->SetDirection(sample->GetDirection());
+    image->Allocate();
+    return image;
+  }
+  
+  
+  //! allocate volume of the same dimension,spacing and origin and do nearest neighbour resampling
+  template<class T,class S,class E,class D> void nearest_resample_like(typename T::Pointer &dst,const typename S::Pointer &sample,const typename E::Pointer &src, const D& def)
+  {
+    allocate_same<T,S>(dst,sample);
+		itk::ImageRegionIteratorWithIndex<T> it(dst, dst->GetLargestPossibleRegion());
+		for(it.GoToBegin(); !it.IsAtEnd(); ++it)
+    {
+      tag_point p;
+      typename E::IndexType idx;
+      dst->TransformIndexToPhysicalPoint(it.GetIndex(),p);
+      if(src->TransformPhysicalPointToIndex(p,idx))
+      {
+        it.Value()=src->GetPixel(idx);
+      }else{
+        it.Value()=def;
+      }
+    }
+  }
+  
+  //! check if volumes have the same dimensions, spacing and origin
+  template<class T,class S> bool check_same(typename T::Pointer image,typename S::Pointer sample)
+  {
+		return
+      (image->GetLargestPossibleRegion() == sample->GetLargestPossibleRegion()) &&
+      (image->GetSpacing() == sample->GetSpacing()) &&
+      (image->GetOrigin() == sample->GetOrigin()) &&
+      (image->GetDirection().GetVnlMatrix()  == sample->GetDirection().GetVnlMatrix()); // carefull here! , maybe we should calculate some kind of difference here ?
+      // this is warkaround a bug in itk
+  }
+  
+  //! allocate volume
+  //! \param[out] image - volume to allocate
+  //! \param dims - dimensions (voxels)
+  //! \param spacing - volume spacing (mm)
+  //! \param origin  - volume origin (mm)
+  template<class T> void allocate_image3d(typename T::Pointer &image, 
+      const itk::Array<unsigned int> &dims, 
+      const itk::Array<double>& spacing, 
+      const itk::Array<double>& origin)
+	{
+		image3d_complex::SizeType  imageSize3D = {{ dims[0], dims[1], dims[2]}};
+		image3d_complex::IndexType startIndex3D = { {0, 0, 0}};
+		image3d_complex::RegionType region;
+		region.SetSize  (imageSize3D);
+		region.SetIndex (startIndex3D);
+		image->SetLargestPossibleRegion (region);
+		image->SetBufferedRegion (region);
+		image->SetRequestedRegion (region);
+		image->SetSpacing( spacing );
+		image->SetOrigin( origin );
+		image->Allocate ();
+	}
+  
+  //! allocate volume
+  //! \param[out] image - volume to allocate
+  //! \param dims - dimensions (voxels)
+  //! \param spacing - volume spacing (mm)
+  //! \param origin  - volume origin (mm)
+  template<class T> void allocate_image3d(typename T::Pointer &image, 
+      const itk::Vector<unsigned int,3> &dims, 
+      const itk::Vector<double,3>& spacing, 
+      const itk::Vector<double,3>& origin)
+	{
+		image3d_complex::SizeType  imageSize3D = {{ dims[0], dims[1], dims[2]}};
+		image3d_complex::IndexType startIndex3D = { {0, 0, 0}};
+		image3d_complex::RegionType region;
+		region.SetSize  (imageSize3D);
+		region.SetIndex (startIndex3D);
+		image->SetLargestPossibleRegion (region);
+		image->SetBufferedRegion (region);
+		image->SetRequestedRegion (region);
+		image->SetSpacing( spacing );
+		image->SetOrigin( origin.GetDataPointer () );
+		image->Allocate ();
+	}
+  
+  //! allocate volume
+  //! \param[out] image - volume to allocate
+  //! \param dims - dimensions (voxels)
+  //! \param spacing - volume spacing (mm)
+  //! \param origin  - volume origin (mm)
+  template<class T> void allocate_image3d(typename T::Pointer &image, 
+      const fixed_vec<3, unsigned int>&dims, 
+      const fixed_vec<3, double>& spacing=fixed_vec<3, double>(1.0) , 
+      const fixed_vec<3, double>& origin=fixed_vec<3, double>(0.0))
+	{
+		image3d_complex::SizeType  imageSize3D = {{ dims[0], dims[1], dims[2]}};
+		image3d_complex::IndexType startIndex3D = { {0, 0, 0}};
+		image3d_complex::RegionType region;
+		region.SetSize  (imageSize3D);
+		region.SetIndex (startIndex3D);
+		image->SetLargestPossibleRegion (region);
+		image->SetBufferedRegion (region);
+		image->SetRequestedRegion (region);
+		image->SetSpacing( spacing.c_buf() );
+		image->SetOrigin( origin.c_buf() );
+		image->Allocate ();
+	}
+
+  
+  inline image3d::SizeType operator/= (image3d::SizeType & s, int d)
+  {
+    s[0] /= d;
+    s[1] /= d;
+    s[2] /= d;
+    return s;
+  }
+
+  inline image3d::SizeType operator*= (image3d::SizeType & s, int d)
+  {
+    s[0] *= d;
+    s[1] *= d;
+    s[2] *= d;
+    return s;
+  }
+  
+// a helper function for minc reading
+  template <class T> typename T::Pointer load_minc(const char *file)
+  {
+    typedef itk::MincImageIO ImageIOType;
+    ImageIOType::Pointer minc2ImageIO = ImageIOType::New();
+     
+    typename itk::ImageFileReader<T>::Pointer reader = itk::ImageFileReader<T>::New();
+    
+    reader->SetFileName(file);
+    reader->SetImageIO( minc2ImageIO );
+    reader->Update();
+    
+    return reader->GetOutput();
+  }
+
+  
+  void set_minc_storage_type(itk::Object* image,nc_type datatype,bool is_signed);
+  void copy_metadata(itk::Object* dst,itk::Object* src);
+  void copy_dimorder(itk::Object* dst,itk::Object* src);
+  void append_history(itk::Object* dst,const std::string& history);
+   
+  // a helper function for minc writing
+  template <class T> void save_minc(const char *file,typename T::Pointer img)
+  {
+    typedef itk::MincImageIO ImageIOType;
+    ImageIOType::Pointer minc2ImageIO = ImageIOType::New();
+     
+    typename itk::ImageFileWriter< T >::Pointer writer = itk::ImageFileWriter<T>::New();
+    writer->SetFileName(file);
+    writer->SetImageIO( minc2ImageIO );
+    writer->SetInput( img );
+    writer->Update();
+  } 
+  
+  //! allocate volume with spacing 1mm and origin 0,0,0
+  //! \param[out] image - volume to allocate
+  //! \param dims - dimensions (voxels)
+  template<class T> void allocate_image3d(typename T::Pointer &image, const itk::Size<3> &dims)
+  {
+    allocate_image3d<T>(image,IDX<unsigned int>(dims[0],dims[1],dims[2]));
+  }
+
+  //! calculate volume min and max
+  int get_image_limits(image3d::Pointer, voxel_type &min, voxel_type &max);
+  //! calculate volume min and max
+  int get_image_limits(def3d::Pointer, voxel_type &min, voxel_type &max);
+  //! calculate volume min and max
+  int get_image_limits(mask3d::Pointer img, voxel_type &min,voxel_type &max);
+  
+  //! store tags to minc tags file
+  void write_tags(const tag_points& tags, const char * file);
+  //! store two sets of tags to minc tags file
+  void write_2tags(const tag_points& tags,const tag_points& tags2, const char * file);
+  
+  //! store tags and labels
+  void write_tags(const tag_points& tags,const std::vector<int>& labels, const char * file);
+  //! store tags and values
+  void write_tags(const tag_points& tags,const std::vector<float>& values, const char * file);
+  //! store tags and values
+  void write_tags(const tag_points& tags,const std::vector<double>& values, const char * file);
+  
+  
+  //! read tags from the minc tag file
+  void read_tags(tag_points& tags, const char * file,int vol=1);
+  
+  //! read tags and labels from minc tag file
+  void read_tags(tag_points& tags, std::vector<int>& labels, const char * file, int vol=1);
+  
+  //! read tags and labels from minc tag file
+  void read_tags(tag_points& tags, std::vector<float>& labels, const char * file, int vol=1);
+  
+  //! read tags and labels from minc tag file
+  void read_tags(tag_points& tags, std::vector<double>& labels, const char * file, int vol=1);
+
+  //! read tags and labels from minc tag file
+  void read_tags(tag_points& tag1, tag_points& tag2,std::vector<double>& labels, const char * file);
+  
+  
+  //! read array from the text file
+  void load_parameters(const char *file,itk::Array<double> &param);
+  //! save array to the text file
+  void save_parameters(const char *file,const itk::Array<double> &param);
+  //! read array from the text file, up to components
+  void load_parameters(const char *file,itk::Array<double> &param,int no);
+  //! make sure that all voxels are 0 or 1
+  void normalize_mask(mask3d::Pointer img);
+  
+  void read_linear_xfm(const char *xfm,itk::Matrix<double,3,3>& rot, itk::Vector<double,3>& tran );
+  void read_linear_xfm(const char *xfm,itk::Matrix<double,2,2>& rot, itk::Vector<double,2>& tran );
+  
+  void write_linear_xfm(const char *xfm,const itk::Matrix<double,3,3>& rot,const itk::Vector<double,3>& tran);
+  void write_linear_xfm(const char *xfm,const itk::Matrix<double,2,2>& rot,const itk::Vector<double,2>& tran);
+  
+  void write_combined_xfm(const char *xfm,const itk::Matrix<double,3,3>& rot,const itk::Vector<double,3>& tran, const char *grid );
+  void write_combined_xfm(const char *xfm,const itk::Matrix<double,2,2>& rot,const itk::Vector<double,2>& tran, const char *grid );
+  
+  void write_combined_xfm(const char *xfm,const char *grid, const itk::Matrix<double,3,3>& rot,const itk::Vector<double,3>& tran );
+  void write_combined_xfm(const char *xfm,const char *grid, const itk::Matrix<double,2,2>& rot,const itk::Vector<double,2>& tran );
+  
+  void write_nonlinear_xfm(const char *xfm,const char *grid);
+
+  //! minc4itk compatibility function
+  template <class T> void  load_minc(const char *file,typename T::Pointer& img)
+  {
+    img=load_minc<T>(file);
+  }
+  
+  template<class T> void setup_itk_image(const minc_1_base& minc_rw, typename T::Pointer& img)
+  {
+    itk::Vector< unsigned int,3> dims;
+    itk::Vector< double,3> spacing;
+    itk::Vector< double,3> origin;
+    itk::Vector< double,3> start;
+    itk::Matrix< double, 3, 3> dir_cos;
+    dir_cos.SetIdentity();
+    //std::cout<<"setup_itk_image"<<std::endl;
+    for(int i=0;i<3;i++)
+    {
+      dims[i]=minc_rw.ndim(i+1);
+      spacing[i]=minc_rw.nspacing(i+1);
+      start[i]=minc_rw.nstart(i+1);
+      if(minc_rw.have_dir_cos(i+1))
+      {
+        for(int j=0;j<3;j++)
+          dir_cos[j][i]=minc_rw.ndir_cos(i+1,j); //TODO: check transpose?
+      }
+      //std::cout<<start[i]<<"\t";
+    }
+    //std::cout<<std::endl;
+    origin=dir_cos*start;
+    allocate_image3d<T>(img,dims,spacing,origin);
+    img->SetDirection(dir_cos);
+  }
+  
+  template<class T> void imitate_minc (const char *path, typename T::Pointer &img)
+  {
+    minc_1_reader rdr;
+    rdr.open(path,true,true);
+    setup_itk_image<T>(rdr,img);
+  }
+
+};
+
+#endif //_MINC_HELPERS_H_
--- a/progs/CMakeLists.txt
+++ b/progs/CMakeLists.txt
@@ -2,137 +2,163 @@
 #
 # Andrew Janke - a.janke@gmail.com
 
-#SET(CMAKE_MODULE_PATH "../cmake-modules")
+#SET(CMAKE_MODULE_PATH "cmake-modules")
 
-LINK_DIRECTORIES(../)
+#LINK_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/..)
 INCLUDE_DIRECTORIES(Proglib)
-LINK_LIBRARIES( minc2 ${NETCDF_LIBRARY} ${HDF5_LIBRARY} )
+
+LINK_LIBRARIES( ${minc_LIB} )
 ADD_DEFINITIONS(-DHAVE_CONFIG_H)
 
-SET(BISON_FIND_REQUIRED)
-SET(FLEX_FIND_REQUIRED)
+#SET(BISON_FIND_REQUIRED)
+#SET(FLEX_FIND_REQUIRED)
+
 FIND_PACKAGE(BISON)
 FIND_PACKAGE(FLEX)
 
 # all the progs
-ADD_EXECUTABLE(../invert_raw_image mincview/invert_raw_image.c)
-ADD_EXECUTABLE(../mincaverage mincaverage/mincaverage.c)
+ADD_EXECUTABLE(invert_raw_image mincview/invert_raw_image.c)
+ADD_EXECUTABLE(mincaverage mincaverage/mincaverage.c)
+
+IF(BISON_FOUND AND FLEX_FOUND)
+  include_directories(${CMAKE_CURRENT_BINARY_DIR} minccalc)
+  
+  BISON_TARGET(gram ${CMAKE_CURRENT_SOURCE_DIR}/minccalc/gram.y ${CMAKE_CURRENT_BINARY_DIR}/gram.c COMPILE_FLAGS "--debug")
+  FLEX_TARGET(lex ${CMAKE_CURRENT_SOURCE_DIR}/minccalc/lex.l ${CMAKE_CURRENT_BINARY_DIR}/lex.c  )
+  #ADD_FLEX_BISON_DEPENDENCY(gram lex)
+
+  ADD_EXECUTABLE(minccalc 
+                  minccalc/minccalc.c
+                  minccalc/eval.c
+                  minccalc/ident.c
+                  minccalc/node.c
+                  minccalc/optim.c
+                  minccalc/scalar.c
+                  minccalc/sym.c
+                  minccalc/vector.c
+                  ${FLEX_lex_OUTPUTS}
+                  ${BISON_gram_OUTPUTS}
+                 )
+
+  TARGET_LINK_LIBRARIES(minccalc ${FLEX_LIBRARIES})
 
-BISON_TARGET(../minccalc minccalc/gram.y minccalc/gram.c COMPILE_FLAGS "--debug")
-FLEX_TARGET(../minccalc minccalc/lex.l minccalc/lex.c)
-ADD_EXECUTABLE(../minccalc minccalc/minccalc.c
-                           minccalc/gram.c
-                           minccalc/eval.c
-                           minccalc/ident.c
-                           minccalc/lex.c
-                           minccalc/node.c
-                           minccalc/optim.c
-                           minccalc/scalar.c
-                           minccalc/sym.c
-                           minccalc/vector.c)
+  INSTALL( TARGETS minccalc  DESTINATION bin)
+
+  include_directories(${CMAKE_CURRENT_BINARY_DIR} mincgen)
+  BISON_TARGET(ncgentab ${CMAKE_CURRENT_SOURCE_DIR}/mincgen/ncgentab.y ${CMAKE_CURRENT_BINARY_DIR}/ncgentab.c)
+  FLEX_TARGET(ncgenyy ${CMAKE_CURRENT_SOURCE_DIR}/mincgen/ncgenyy.l ${CMAKE_CURRENT_BINARY_DIR}/ncgenyy.c)
+  #ADD_FLEX_BISON_DEPENDENCY(ncgenyy ncgentab)
 
-ADD_EXECUTABLE(../mincconcat mincconcat/mincconcat.c)
-ADD_EXECUTABLE(../mincconvert mincconvert/mincconvert.c)
-ADD_EXECUTABLE(../minccopy minccopy/minccopy.c)
+  ADD_EXECUTABLE(mincgen mincgen/main.c
+                            ${BISON_ncgentab_OUTPUTS}
+                            ${FLEX_ncgenyy_OUTPUTS}
+                            mincgen/escapes.c
+                            mincgen/genlib.c
+                            mincgen/getfill.c
+                            mincgen/init.c
+                            mincgen/load.c)
+  INSTALL( TARGETS mincgen    DESTINATION bin)
 
-ADD_EXECUTABLE(../mincdump mincdump/mincdump.c
+  TARGET_LINK_LIBRARIES(mincgen ${FLEX_LIBRARIES})
+
+ENDIF(BISON_FOUND AND FLEX_FOUND)
+
+ADD_EXECUTABLE(mincconcat mincconcat/mincconcat.c)
+ADD_EXECUTABLE(mincconvert mincconvert/mincconvert.c)
+ADD_EXECUTABLE(minccopy minccopy/minccopy.c)
+
+ADD_EXECUTABLE(mincdump mincdump/mincdump.c
                             mincdump/vardata.c
                             mincdump/dumplib.c)
                             
-ADD_EXECUTABLE(../mincexample1 mincexample/mincexample1.c)
-ADD_EXECUTABLE(../mincexample2 mincexample/mincexample2.c)
-ADD_EXECUTABLE(../mincexpand mincexpand/mincexpand.c)
-ADD_EXECUTABLE(../mincextract mincextract/mincextract.c)
+ADD_EXECUTABLE(mincexample1 mincexample/mincexample1.c)
+ADD_EXECUTABLE(mincexample2 mincexample/mincexample2.c)
+ADD_EXECUTABLE(mincexpand mincexpand/mincexpand.c)
+ADD_EXECUTABLE(mincextract mincextract/mincextract.c)
+ADD_EXECUTABLE(mincinfo mincinfo/mincinfo.c)
+ADD_EXECUTABLE(minclookup minclookup/minclookup.c)
+ADD_EXECUTABLE(mincmakescalar mincmakescalar/mincmakescalar.c)
+ADD_EXECUTABLE(mincmakevector mincmakevector/mincmakevector.c)
+ADD_EXECUTABLE(mincmath mincmath/mincmath.c)
+ADD_EXECUTABLE(minc_modify_header minc_modify_header/minc_modify_header.c)
 
-BISON_TARGET(../mincgen mincgen/ncgentab.y mincgen/nccentab.c)
-FLEX_TARGET(../mincgen mincgen/ncgenyy.l mincgen/ncgenyy.c)
-ADD_EXECUTABLE(../mincgen mincgen/main.c
-                          mincgen/escapes.c
-                          mincgen/genlib.c
-                          mincgen/getfill.c
-                          mincgen/init.c
-                          mincgen/load.c
-                          mincgen/ncgentab.c
-                          mincgen/ncgenyy.c)
-
-ADD_EXECUTABLE(../mincinfo mincinfo/mincinfo.c)
-ADD_EXECUTABLE(../minclookup minclookup/minclookup.c)
-ADD_EXECUTABLE(../mincmakescalar mincmakescalar/mincmakescalar.c)
-ADD_EXECUTABLE(../mincmakevector mincmakevector/mincmakevector.c)
-ADD_EXECUTABLE(../mincmath mincmath/mincmath.c)
-ADD_EXECUTABLE(../minc_modify_header minc_modify_header/minc_modify_header.c)
-
-ADD_EXECUTABLE(../mincresample mincresample/mincresample.c
+ADD_EXECUTABLE(mincresample mincresample/mincresample.c
                                mincresample/resample_volumes.c
                                Proglib/convert_origin_to_start.c)
-TARGET_LINK_LIBRARIES(../mincresample volume_io2)
+TARGET_LINK_LIBRARIES(mincresample ${volume_io_LIB} ${minc_LIB})
 
-ADD_EXECUTABLE(../mincreshape mincreshape/mincreshape.c
+ADD_EXECUTABLE(mincreshape mincreshape/mincreshape.c
                               mincreshape/copy_data.c)
 
-ADD_EXECUTABLE(../mincstats mincstats/mincstats.c)
-ADD_EXECUTABLE(../minctoraw minctoraw/minctoraw.c)
-ADD_EXECUTABLE(../mincwindow mincwindow/mincwindow.c)
+ADD_EXECUTABLE(mincstats mincstats/mincstats.c)
+ADD_EXECUTABLE(minctoraw minctoraw/minctoraw.c)
+ADD_EXECUTABLE(mincwindow mincwindow/mincwindow.c)
 
-ADD_EXECUTABLE(../rawtominc rawtominc/rawtominc.c
+ADD_EXECUTABLE(rawtominc rawtominc/rawtominc.c
                             Proglib/convert_origin_to_start.c)
 
-ADD_EXECUTABLE(../voxeltoworld coordinates/voxeltoworld.c)
-TARGET_LINK_LIBRARIES(../voxeltoworld volume_io2 minc2)
+ADD_EXECUTABLE(voxeltoworld coordinates/voxeltoworld.c)
+TARGET_LINK_LIBRARIES(voxeltoworld ${volume_io_LIB} ${minc_LIB})
 
-ADD_EXECUTABLE(../worldtovoxel coordinates/worldtovoxel.c)
-TARGET_LINK_LIBRARIES(../worldtovoxel volume_io2 minc2)
+ADD_EXECUTABLE(worldtovoxel coordinates/worldtovoxel.c)
+TARGET_LINK_LIBRARIES(worldtovoxel ${volume_io_LIB} ${minc_LIB})
 
 
-ADD_EXECUTABLE(../transformtags xfm/transformtags.c)
-TARGET_LINK_LIBRARIES(../transformtags volume_io2 minc2)
+ADD_EXECUTABLE(transformtags xfm/transformtags.c)
+TARGET_LINK_LIBRARIES(transformtags ${volume_io_LIB} ${minc_LIB})
 
-ADD_EXECUTABLE(../xfmconcat xfm/xfmconcat.c)
-TARGET_LINK_LIBRARIES(../xfmconcat volume_io2 minc2)
+ADD_EXECUTABLE(xfmconcat xfm/xfmconcat.c)
+TARGET_LINK_LIBRARIES(xfmconcat ${volume_io_LIB} ${minc_LIB})
 
-ADD_EXECUTABLE(../xfminvert xfm/xfminvert.c)
-TARGET_LINK_LIBRARIES(../xfminvert volume_io2 minc2)
+ADD_EXECUTABLE(xfminvert xfm/xfminvert.c)
+TARGET_LINK_LIBRARIES(xfminvert ${volume_io_LIB} ${minc_LIB})
 
 # install progs
 INSTALL(TARGETS
-   ../invert_raw_image 
-   ../mincaverage
-   ../minccalc
-   ../mincconcat
-   ../mincconvert
-   ../minccopy
-   ../mincdump
-#   ../mincexample1
-#   ../mincexample2
-   ../mincexpand
-   ../mincextract
-   ../mincgen
-   ../mincinfo
-   ../minclookup
-   ../mincmakescalar
-   ../mincmakevector
-   ../mincmath
-   ../minc_modify_header
-   ../mincresample
-   ../mincreshape
-   ../mincstats
-   ../minctoraw
-   ../mincwindow
-   ../rawtominc
-   ../voxeltoworld
-   ../worldtovoxel
-   ../transformtags
-   ../xfmconcat
-   ../xfminvert
+   invert_raw_image 
+   mincaverage
+   mincconcat
+   mincconvert
+   minccopy
+   mincdump
+#   mincexample1
+#   mincexample2
+   mincexpand
+   mincextract
+   mincinfo
+   minclookup
+   mincmakescalar
+   mincmakevector
+   mincmath
+   minc_modify_header
+   mincresample
+   mincreshape
+   mincstats
+   minctoraw
+   mincwindow
+   rawtominc
+   voxeltoworld
+   worldtovoxel
+   transformtags
+   xfmconcat
+   xfminvert
    DESTINATION bin)
 
-
 # perl and shell scripts
 INSTALL(FILES
    mincdiff/mincdiff  
    mincedit/mincedit  
    mincheader/mincheader  
-   minchistory/minchistory  
    mincpik/mincpik  
    mincview/mincview
+   PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ  WORLD_EXECUTE WORLD_READ
    DESTINATION bin )
+
+
+configure_file(minchistory/minchistory.in ${CMAKE_CURRENT_BINARY_DIR}/minchistory @ONLY)
+add_custom_target(minchistory chmod +x ${CMAKE_CURRENT_BINARY_DIR}/minchistory DEPENDS minchistory/minchistory.in)
+
+INSTALL(FILES
+  ${CMAKE_CURRENT_BINARY_DIR}/minchistory
+  PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ  WORLD_EXECUTE WORLD_READ
+   DESTINATION bin )
--- a/progs/minccalc/eval.c
+++ b/progs/minccalc/eval.c
@@ -20,7 +20,7 @@
 scalar_t   eval_index(int, int *, node_t, vector_t, scalar_t);
 scalar_t   eval_sum(int, int *, node_t, vector_t);
 scalar_t   eval_prod(int, int *, node_t, vector_t);
-scalar_t   eval_max(int, int *, node_t, vector_t, double);
+scalar_t   eval_max(int, int *, node_t, vector_t, double, int);
 vector_t   eval_vector(int, int *, node_t, sym_t);
 vector_t   gen_vector(int, int *, node_t, sym_t);
 vector_t   gen_range(int, int *, node_t, sym_t);
@@ -315,13 +315,25 @@
       
    case NODETYPE_MAX:
       v = eval_vector(width, eval_flags, n->expr[0], sym);
-      s = eval_max(width, eval_flags, n, v, 1.0);
+      s = eval_max(width, eval_flags, n, v, 1.0, 0);
       vector_free(v);
       return s;
       
    case NODETYPE_MIN:
       v = eval_vector(width, eval_flags, n->expr[0], sym);
-      s = eval_max(width, eval_flags, n, v, -1.0);
+      s = eval_max(width, eval_flags, n, v, -1.0, 0);
+      vector_free(v);
+      return s;
+      
+   case NODETYPE_IMAX:
+      v = eval_vector(width, eval_flags, n->expr[0], sym);
+      s = eval_max(width, eval_flags, n, v, 1.0, 1);
+      vector_free(v);
+      return s;
+      
+   case NODETYPE_IMIN:
+      v = eval_vector(width, eval_flags, n->expr[0], sym);
+      s = eval_max(width, eval_flags, n, v, -1.0, 1);
       vector_free(v);
       return s;
       
@@ -532,27 +544,29 @@
 }
 
 /* Find the maximum of a vector. Sign should be +1.0 for maxima search
-   and -1.0 for minima search */
+   and -1.0 for minima search.
+   type should be 0 for value and 1 for index */
 scalar_t eval_max(int width, int *eval_flags, 
-                  node_t n, vector_t v, double sign)
+                  node_t n, vector_t v, double sign, int type)
 {
    int i, ivalue;
    scalar_t result;
-   double value, ans;
+   double value, max, idx;
 
    result = new_scalar(width);
    for (ivalue=0; ivalue < width; ivalue++) {
       if (eval_flags != NULL && !eval_flags[ivalue]) continue;
-      result->vals[ivalue] = ans = INVALID_VALUE;
+      result->vals[ivalue] = max = INVALID_VALUE;
       for (i = 0; i < v->len; i++) {
          value = v->el[i]->vals[ivalue];
          if (value != INVALID_VALUE) {
-            if (ans == INVALID_VALUE || (sign*(value-ans) > 0.0)) {
-               ans = value;
+            if (max == INVALID_VALUE || (sign*(value-max) > 0.0)) {
+               max = value;
+               idx = (double)i;
             }
          }
       }
-      result->vals[ivalue] = ans;
+      result->vals[ivalue] = (type == 0) ? max : idx;
    }
    return result;
 }
--- a/progs/minccalc/gram.c
+++ b/progs/minccalc/gram.c
@@ -124,31 +124,33 @@
      LEN = 268,
      MAX = 269,
      MIN = 270,
-     ISNAN = 271,
-     SQRT = 272,
-     ABS = 273,
-     EXP = 274,
-     LOG = 275,
-     SIN = 276,
-     COS = 277,
-     TAN = 278,
-     ASIN = 279,
-     ACOS = 280,
-     ATAN = 281,
-     CLAMP = 282,
-     SEGMENT = 283,
-     LT = 284,
-     LE = 285,
-     GT = 286,
-     GE = 287,
-     EQ = 288,
-     NE = 289,
-     NOT = 290,
-     AND = 291,
-     OR = 292,
-     IF = 293,
-     ELSE = 294,
-     FOR = 295
+     IMAX = 271,
+     IMIN = 272,
+     ISNAN = 273,
+     SQRT = 274,
+     ABS = 275,
+     EXP = 276,
+     LOG = 277,
+     SIN = 278,
+     COS = 279,
+     TAN = 280,
+     ASIN = 281,
+     ACOS = 282,
+     ATAN = 283,
+     CLAMP = 284,
+     SEGMENT = 285,
+     LT = 286,
+     LE = 287,
+     GT = 288,
+     GE = 289,
+     EQ = 290,
+     NE = 291,
+     NOT = 292,
+     AND = 293,
+     OR = 294,
+     IF = 295,
+     ELSE = 296,
+     FOR = 297
    };
 #endif
 /* Tokens.  */
@@ -165,31 +167,33 @@
 #define LEN 268
 #define MAX 269
 #define MIN 270
-#define ISNAN 271
-#define SQRT 272
-#define ABS 273
-#define EXP 274
-#define LOG 275
-#define SIN 276
-#define COS 277
-#define TAN 278
-#define ASIN 279
-#define ACOS 280
-#define ATAN 281
-#define CLAMP 282
-#define SEGMENT 283
-#define LT 284
-#define LE 285
-#define GT 286
-#define GE 287
-#define EQ 288
-#define NE 289
-#define NOT 290
-#define AND 291
-#define OR 292
-#define IF 293
-#define ELSE 294
-#define FOR 295
+#define IMAX 271
+#define IMIN 272
+#define ISNAN 273
+#define SQRT 274
+#define ABS 275
+#define EXP 276
+#define LOG 277
+#define SIN 278
+#define COS 279
+#define TAN 280
+#define ASIN 281
+#define ACOS 282
+#define ATAN 283
+#define CLAMP 284
+#define SEGMENT 285
+#define LT 286
+#define LE 287
+#define GT 288
+#define GE 289
+#define EQ 290
+#define NE 291
+#define NOT 292
+#define AND 293
+#define OR 294
+#define IF 295
+#define ELSE 296
+#define FOR 297
 
 
 
@@ -209,7 +213,7 @@
 
 
 /* Line 214 of yacc.c  */
-#line 213 "progs/minccalc/gram.c"
+#line 217 "progs/minccalc/gram.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -221,7 +225,7 @@
 
 
 /* Line 264 of yacc.c  */
-#line 225 "progs/minccalc/gram.c"
+#line 229 "progs/minccalc/gram.c"
 
 #ifdef short
 # undef short
@@ -434,22 +438,22 @@
 #endif
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  65
+#define YYFINAL  69
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   820
+#define YYLAST   800
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  59
+#define YYNTOKENS  61
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  6
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  61
+#define YYNRULES  63
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  148
+#define YYNSTATES  152
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   295
+#define YYMAXUTOK   297
 
 #define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -461,15 +465,15 @@
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      45,    46,    43,    41,    54,    42,    49,    44,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    57,    56,
-       2,    50,     2,    58,     2,     2,     2,     2,     2,     2,
+      47,    48,    45,    43,    56,    44,    51,    46,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    59,    58,
+       2,    52,     2,    60,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    47,     2,    48,    51,     2,     2,     2,     2,     2,
+       2,    49,     2,    50,    53,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    52,    55,    53,     2,     2,     2,     2,
+       2,     2,     2,    54,    57,    55,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -486,7 +490,7 @@
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40
+      35,    36,    37,    38,    39,    40,    41,    42
 };
 
 #if YYDEBUG
@@ -499,38 +503,39 @@
       81,    85,    89,    93,    97,   101,   105,   109,   113,   118,
      122,   125,   128,   131,   134,   137,   140,   143,   146,   149,
      152,   155,   158,   161,   164,   167,   170,   173,   176,   179,
-     188,   197,   203,   211,   217,   225,   227,   229,   231,   237,
-     243,   245
+     182,   185,   194,   203,   209,   217,   223,   231,   233,   235,
+     237,   243,   249,   251
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      60,     0,    -1,    61,    -1,    62,    56,    61,    -1,    62,
-      56,    -1,    62,    -1,    45,    62,    46,    -1,    52,    61,
-      53,    -1,    47,    64,    48,    -1,    52,     6,     4,    62,
-      55,    62,    53,    -1,    45,    62,    57,    62,    46,    -1,
-      45,    62,    57,    62,    48,    -1,    47,    62,    57,    62,
-      46,    -1,    47,    62,    57,    62,    48,    -1,    62,    41,
-      62,    -1,    62,    42,    62,    -1,    42,    62,    -1,    62,
-      43,    62,    -1,    62,    44,    62,    -1,    62,    51,    62,
-      -1,    62,    29,    62,    -1,    62,    30,    62,    -1,    62,
-      31,    62,    -1,    62,    32,    62,    -1,    62,    33,    62,
-      -1,    62,    34,    62,    -1,    62,    36,    62,    -1,    62,
-      37,    62,    -1,    62,    47,    62,    48,    -1,     6,    50,
-      62,    -1,    11,    63,    -1,    35,    62,    -1,    10,    62,
-      -1,     9,    62,    -1,     8,    62,    -1,    13,    62,    -1,
-      14,    62,    -1,    15,    62,    -1,    16,    62,    -1,    17,
-      62,    -1,    18,    62,    -1,    19,    62,    -1,    20,    62,
-      -1,    21,    62,    -1,    22,    62,    -1,    23,    62,    -1,
-      24,    62,    -1,    25,    62,    -1,    26,    62,    -1,    27,
-      45,    62,    54,    62,    54,    62,    46,    -1,    28,    45,
-      62,    54,    62,    54,    62,    46,    -1,    62,    58,    62,
-      57,    62,    -1,    38,    45,    62,    46,    62,    39,    62,
-      -1,    38,    45,    62,    46,    62,    -1,    40,    52,     6,
-       4,    62,    53,    62,    -1,     6,    -1,     7,    -1,     3,
-      -1,     6,    50,    62,    54,    63,    -1,     6,    50,    62,
-       4,    62,    -1,    62,    -1,    64,    54,    62,    -1
+      62,     0,    -1,    63,    -1,    64,    58,    63,    -1,    64,
+      58,    -1,    64,    -1,    47,    64,    48,    -1,    54,    63,
+      55,    -1,    49,    66,    50,    -1,    54,     6,     4,    64,
+      57,    64,    55,    -1,    47,    64,    59,    64,    48,    -1,
+      47,    64,    59,    64,    50,    -1,    49,    64,    59,    64,
+      48,    -1,    49,    64,    59,    64,    50,    -1,    64,    43,
+      64,    -1,    64,    44,    64,    -1,    44,    64,    -1,    64,
+      45,    64,    -1,    64,    46,    64,    -1,    64,    53,    64,
+      -1,    64,    31,    64,    -1,    64,    32,    64,    -1,    64,
+      33,    64,    -1,    64,    34,    64,    -1,    64,    35,    64,
+      -1,    64,    36,    64,    -1,    64,    38,    64,    -1,    64,
+      39,    64,    -1,    64,    49,    64,    50,    -1,     6,    52,
+      64,    -1,    11,    65,    -1,    37,    64,    -1,    10,    64,
+      -1,     9,    64,    -1,     8,    64,    -1,    13,    64,    -1,
+      14,    64,    -1,    15,    64,    -1,    16,    64,    -1,    17,
+      64,    -1,    18,    64,    -1,    19,    64,    -1,    20,    64,
+      -1,    21,    64,    -1,    22,    64,    -1,    23,    64,    -1,
+      24,    64,    -1,    25,    64,    -1,    26,    64,    -1,    27,
+      64,    -1,    28,    64,    -1,    29,    47,    64,    56,    64,
+      56,    64,    48,    -1,    30,    47,    64,    56,    64,    56,
+      64,    48,    -1,    64,    60,    64,    59,    64,    -1,    40,
+      47,    64,    48,    64,    41,    64,    -1,    40,    47,    64,
+      48,    64,    -1,    42,    54,     6,     4,    64,    55,    64,
+      -1,     6,    -1,     7,    -1,     3,    -1,     6,    52,    64,
+      56,    65,    -1,     6,    52,    64,     4,    64,    -1,    64,
+      -1,    66,    56,    64,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
@@ -539,10 +544,10 @@
        0,    53,    53,    57,    64,    67,    71,    74,    77,    80,
       88,    96,   104,   112,   120,   128,   136,   146,   154,   162,
      170,   178,   186,   194,   202,   210,   218,   226,   234,   241,
-     248,   251,   258,   264,   270,   276,   282,   288,   294,   301,
-     308,   315,   322,   329,   336,   343,   350,   357,   364,   371,
-     380,   389,   397,   405,   412,   420,   426,   432,   441,   448,
-     457,   462
+     248,   251,   258,   264,   270,   276,   282,   288,   294,   300,
+     306,   313,   320,   327,   334,   341,   348,   355,   362,   369,
+     376,   383,   392,   401,   409,   417,   424,   432,   438,   444,
+     453,   460,   469,   474
 };
 #endif
 
@@ -552,12 +557,13 @@
 static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "NAN", "IN", "TO", "IDENT", "REAL",
-  "AVG", "PROD", "SUM", "LET", "NEG", "LEN", "MAX", "MIN", "ISNAN", "SQRT",
-  "ABS", "EXP", "LOG", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN",
-  "CLAMP", "SEGMENT", "LT", "LE", "GT", "GE", "EQ", "NE", "NOT", "AND",
-  "OR", "IF", "ELSE", "FOR", "'+'", "'-'", "'*'", "'/'", "'('", "')'",
-  "'['", "']'", "'.'", "'='", "'^'", "'{'", "'}'", "','", "'|'", "';'",
-  "':'", "'?'", "$accept", "top", "exprlist", "expr", "letexpr", "vector", 0
+  "AVG", "PROD", "SUM", "LET", "NEG", "LEN", "MAX", "MIN", "IMAX", "IMIN",
+  "ISNAN", "SQRT", "ABS", "EXP", "LOG", "SIN", "COS", "TAN", "ASIN",
+  "ACOS", "ATAN", "CLAMP", "SEGMENT", "LT", "LE", "GT", "GE", "EQ", "NE",
+  "NOT", "AND", "OR", "IF", "ELSE", "FOR", "'+'", "'-'", "'*'", "'/'",
+  "'('", "')'", "'['", "']'", "'.'", "'='", "'^'", "'{'", "'}'", "','",
+  "'|'", "';'", "':'", "'?'", "$accept", "top", "exprlist", "expr",
+  "letexpr", "vector", 0
 };
 #endif
 
@@ -570,21 +576,22 @@
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
      285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,    43,    45,    42,    47,    40,    41,    91,    93,    46,
-      61,    94,   123,   125,    44,   124,    59,    58,    63
+     295,   296,   297,    43,    45,    42,    47,    40,    41,    91,
+      93,    46,    61,    94,   123,   125,    44,   124,    59,    58,
+      63
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    59,    60,    61,    61,    61,    62,    62,    62,    62,
-      62,    62,    62,    62,    62,    62,    62,    62,    62,    62,
-      62,    62,    62,    62,    62,    62,    62,    62,    62,    62,
-      62,    62,    62,    62,    62,    62,    62,    62,    62,    62,
-      62,    62,    62,    62,    62,    62,    62,    62,    62,    62,
-      62,    62,    62,    62,    62,    62,    62,    62,    63,    63,
-      64,    64
+       0,    61,    62,    63,    63,    63,    64,    64,    64,    64,
+      64,    64,    64,    64,    64,    64,    64,    64,    64,    64,
+      64,    64,    64,    64,    64,    64,    64,    64,    64,    64,
+      64,    64,    64,    64,    64,    64,    64,    64,    64,    64,
+      64,    64,    64,    64,    64,    64,    64,    64,    64,    64,
+      64,    64,    64,    64,    64,    64,    64,    64,    64,    64,
+      65,    65,    66,    66
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -594,9 +601,9 @@
        5,     5,     5,     5,     3,     3,     2,     3,     3,     3,
        3,     3,     3,     3,     3,     3,     3,     3,     4,     3,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     8,
-       8,     5,     7,     5,     7,     1,     1,     1,     5,     5,
-       1,     3
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     8,     8,     5,     7,     5,     7,     1,     1,     1,
+       5,     5,     1,     3
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -604,55 +611,57 @@
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,    57,    55,    56,     0,     0,     0,     0,     0,     0,
+       0,    59,    57,    58,     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,     2,     5,     0,    34,    33,    32,     0,    30,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,     0,     0,    31,     0,     0,    16,
-       0,    60,     0,    55,     0,     1,     0,     0,     0,     0,
+       0,     0,     0,     0,     2,     5,     0,    34,    33,    32,
+       0,    30,    35,    36,    37,    38,    39,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,     0,     0,
+      31,     0,     0,    16,     0,    62,     0,    57,     0,     1,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       4,     0,    29,     0,     0,     0,     0,     0,     6,     0,
-       0,     8,     0,     0,     7,    20,    21,    22,    23,    24,
-      25,    26,    27,    14,    15,    17,    18,     0,    19,     3,
-       0,     0,     0,     0,     0,     0,     0,     0,    61,     0,
-      28,     0,     0,     0,     0,     0,    53,     0,    10,    11,
-      12,    13,     0,    51,    59,    58,     0,     0,     0,     0,
-       0,     0,     0,    52,    54,     9,    49,    50
+       0,     0,     0,     0,     4,     0,    29,     0,     0,     0,
+       0,     0,     6,     0,     0,     8,     0,     0,     7,    20,
+      21,    22,    23,    24,    25,    26,    27,    14,    15,    17,
+      18,     0,    19,     3,     0,     0,     0,     0,     0,     0,
+       0,     0,    63,     0,    28,     0,     0,     0,     0,     0,
+      55,     0,    10,    11,    12,    13,     0,    53,    61,    60,
+       0,     0,     0,     0,     0,     0,     0,    54,    56,     9,
+      51,    52
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,    31,    32,    33,    39,    62
+      -1,    33,    34,    35,    41,    66
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -76
+#define YYPACT_NINF -48
 static const yytype_int16 yypact[] =
 {
-     161,   -76,   -21,   -76,   161,   161,   161,    30,   161,   161,
-     161,   161,   161,   161,   161,   161,   161,   161,   161,   161,
-     161,   161,    -7,    -5,   161,    -3,    -9,   161,   161,   161,
-     208,    44,   -76,   308,   161,     0,     0,     0,     2,   -76,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   161,   161,   -12,   161,    39,   -12,
-     232,   338,   -27,    -1,     1,   -76,   161,   161,   161,   161,
-     161,   161,   161,   161,   161,   161,   161,   161,   161,   161,
-     161,   161,   723,   161,   368,   398,   428,    42,   -76,   161,
-     161,   -76,   161,   161,   -76,   -10,   -10,   -10,   -10,   769,
-     769,    72,   746,   -25,   -25,   -12,   -12,   451,   -12,   -76,
-     474,   108,   161,   161,   161,   161,   262,   285,   723,   504,
-     -76,   161,   161,    30,   534,   564,   594,   617,   -76,   -76,
-     -76,   -76,   161,   723,   723,   -76,   161,   161,   161,   161,
-     647,   677,   700,   723,   723,   -76,   -76,   -76
+     167,   -48,   -21,   -48,   167,   167,   167,    27,   167,   167,
+     167,   167,   167,   167,   167,   167,   167,   167,   167,   167,
+     167,   167,   167,   167,     6,    11,   167,    12,   -11,   167,
+     167,   167,   216,    45,   -48,     3,   167,     1,     1,     1,
+       8,   -48,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,   167,   167,
+      -9,   167,    56,    -9,   240,   316,   -27,    -1,     9,   -48,
+     167,   167,   167,   167,   167,   167,   167,   167,   167,   167,
+     167,   167,   167,   167,   167,   167,   701,   167,   346,   376,
+     406,    61,   -48,   167,   167,   -48,   167,   167,   -48,    42,
+      42,    42,    42,   747,   747,    74,   724,   -25,   -25,    -9,
+      -9,   429,    -9,   -48,   452,   112,   167,   167,   167,   167,
+     270,   293,   701,   482,   -48,   167,   167,    27,   512,   542,
+     572,   595,   -48,   -48,   -48,   -48,   167,   701,   701,   -48,
+     167,   167,   167,   167,   625,   655,   678,   701,   701,   -48,
+     -48,   -48
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -76,   -76,    -2,    -4,   -75,   -76
+     -48,   -48,    -2,    -4,   -47,   -48
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -662,176 +671,172 @@
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      35,    36,    37,    93,    40,    41,    42,    43,    44,    45,
-      46,    47,    48,    49,    50,    51,    52,    53,    76,    77,
-      56,    91,    78,    59,    60,    61,    79,    92,    64,    34,
-      82,    74,    75,    76,    77,    78,    38,    78,    54,    79,
-      55,    79,    57,    58,    65,    87,   115,    78,   135,    34,
-      84,    85,    83,    86,    94,     0,     0,     0,     0,     0,
-       0,     0,    95,    96,    97,    98,    99,   100,   101,   102,
-     103,   104,   105,   106,   107,   108,     0,   110,   109,   111,
-       0,     0,     0,     0,     0,   116,   117,     0,   118,   119,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    66,    67,    68,    69,    70,    71,     0,   124,   125,
-     126,   127,   122,    74,    75,    76,    77,   133,   134,    78,
-       0,     0,     0,    79,     0,     0,     0,     0,   140,     0,
-       0,     0,   141,   142,   143,   144,     0,    66,    67,    68,
-      69,    70,    71,     0,    72,    73,     0,     0,     0,    74,
-      75,    76,    77,     0,     0,    78,     0,     0,     0,    79,
-       0,     0,   123,     0,     1,     0,    81,     2,     3,     4,
-       5,     6,     7,     0,     8,     9,    10,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
-       0,     0,     0,     0,     0,     0,    24,     0,     0,    25,
-       0,    26,     0,    27,     0,     0,    28,     0,    29,     0,
-       0,     1,     0,    30,    63,     3,     4,     5,     6,     7,
-       0,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,     0,     0,     0,
-       0,     0,     0,    24,     0,     0,    25,     0,    26,     0,
-      27,     0,     0,    28,     0,    29,     0,     0,     0,     0,
-      30,    66,    67,    68,    69,    70,    71,     0,    72,    73,
-       0,     0,     0,    74,    75,    76,    77,     0,    88,    78,
-       0,     0,     0,    79,     0,     0,     0,     0,     0,    89,
-      81,    66,    67,    68,    69,    70,    71,     0,    72,    73,
-       0,     0,     0,    74,    75,    76,    77,     0,   128,    78,
-     129,     0,     0,    79,    66,    67,    68,    69,    70,    71,
-      81,    72,    73,     0,     0,     0,    74,    75,    76,    77,
-       0,   130,    78,   131,     0,     0,    79,    66,    67,    68,
-      69,    70,    71,    81,    72,    73,     0,     0,     0,    74,
-      75,    76,    77,     0,     0,    78,     0,     0,     0,    79,
-       0,     0,     0,     0,    80,     0,    81,    66,    67,    68,
-      69,    70,    71,     0,    72,    73,     0,     0,     0,    74,
-      75,    76,    77,     0,     0,    78,     0,     0,     0,    79,
-       0,     0,     0,     0,     0,    90,    81,    66,    67,    68,
-      69,    70,    71,     0,    72,    73,     0,     0,     0,    74,
-      75,    76,    77,     0,     0,    78,     0,     0,     0,    79,
-       0,     0,   112,     0,     0,     0,    81,    66,    67,    68,
-      69,    70,    71,     0,    72,    73,     0,     0,     0,    74,
-      75,    76,    77,     0,     0,    78,     0,     0,     0,    79,
-       0,     0,   113,     0,     0,     0,    81,    66,    67,    68,
-      69,    70,    71,     0,    72,    73,     0,     0,     0,    74,
-      75,    76,    77,     0,   114,    78,     0,     0,     0,    79,
-      66,    67,    68,    69,    70,    71,    81,    72,    73,     0,
-       0,     0,    74,    75,    76,    77,     0,     0,    78,   120,
-       0,     0,    79,    66,    67,    68,    69,    70,    71,    81,
-      72,    73,     0,     0,     0,    74,    75,    76,    77,     0,
-       0,    78,     0,     0,     0,    79,     0,     0,     0,     0,
-       0,   121,    81,    66,    67,    68,    69,    70,    71,     0,
-      72,    73,     0,     0,     0,    74,    75,    76,    77,     0,
-       0,    78,     0,     0,     0,    79,     0,     0,     0,   132,
-       0,     0,    81,    66,    67,    68,    69,    70,    71,     0,
-      72,    73,     0,     0,     0,    74,    75,    76,    77,     0,
-       0,    78,     0,     0,     0,    79,     0,     0,   136,     0,
-       0,     0,    81,    66,    67,    68,    69,    70,    71,     0,
-      72,    73,     0,     0,     0,    74,    75,    76,    77,     0,
-       0,    78,     0,     0,     0,    79,     0,     0,   137,     0,
-       0,     0,    81,    66,    67,    68,    69,    70,    71,     0,
-      72,    73,     0,   138,     0,    74,    75,    76,    77,     0,
-       0,    78,     0,     0,     0,    79,    66,    67,    68,    69,
-      70,    71,    81,    72,    73,     0,     0,     0,    74,    75,
-      76,    77,     0,     0,    78,     0,     0,     0,    79,     0,
-     139,     0,     0,     0,     0,    81,    66,    67,    68,    69,
-      70,    71,     0,    72,    73,     0,     0,     0,    74,    75,
-      76,    77,     0,     0,    78,     0,     0,     0,    79,     0,
-     145,     0,     0,     0,     0,    81,    66,    67,    68,    69,
-      70,    71,     0,    72,    73,     0,     0,     0,    74,    75,
-      76,    77,     0,   146,    78,     0,     0,     0,    79,    66,
-      67,    68,    69,    70,    71,    81,    72,    73,     0,     0,
-       0,    74,    75,    76,    77,     0,   147,    78,     0,     0,
-       0,    79,    66,    67,    68,    69,    70,    71,    81,    72,
-      73,     0,     0,     0,    74,    75,    76,    77,     0,     0,
-      78,     0,     0,     0,    79,    66,    67,    68,    69,    70,
-      71,    81,    72,     0,     0,     0,     0,    74,    75,    76,
-      77,     0,     0,    78,     0,     0,     0,    79,    66,    67,
-      68,    69,     0,     0,     0,     0,     0,     0,     0,     0,
-      74,    75,    76,    77,     0,     0,    78,     0,     0,     0,
-      79
+      37,    38,    39,    97,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      80,    81,    60,    95,    82,    63,    64,    65,    83,    96,
+      68,    36,    86,    40,    70,    71,    72,    73,    74,    75,
+      82,    76,    77,    62,    83,    69,    78,    79,    80,    81,
+      82,    36,    82,    58,    88,    89,    83,    90,    59,    61,
+      87,    84,    91,    85,    98,   119,    99,   100,   101,   102,
+     103,   104,   105,   106,   107,   108,   109,   110,   111,   112,
+     139,   114,   113,   115,     0,    78,    79,    80,    81,   120,
+     121,    82,   122,   123,     0,    83,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    70,    71,    72,    73,    74,
+      75,     0,   128,   129,   130,   131,   126,    78,    79,    80,
+      81,   137,   138,    82,     0,     0,     0,    83,     0,     0,
+       0,     0,   144,     0,     0,     0,   145,   146,   147,   148,
+       0,     0,     0,    70,    71,    72,    73,    74,    75,     0,
+      76,    77,     0,     0,     0,    78,    79,    80,    81,     0,
+       0,    82,     0,     0,     0,    83,     0,     0,   127,     0,
+       1,     0,    85,     2,     3,     4,     5,     6,     7,     0,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,     0,     0,
+       0,     0,     0,     0,    26,     0,     0,    27,     0,    28,
+       0,    29,     0,     0,    30,     0,    31,     0,     0,     1,
+       0,    32,    67,     3,     4,     5,     6,     7,     0,     8,
+       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,     0,     0,     0,
+       0,     0,     0,    26,     0,     0,    27,     0,    28,     0,
+      29,     0,     0,    30,     0,    31,     0,     0,     0,     0,
+      32,    70,    71,    72,    73,    74,    75,     0,    76,    77,
+       0,     0,     0,    78,    79,    80,    81,     0,    92,    82,
+       0,     0,     0,    83,     0,     0,     0,     0,     0,    93,
+      85,    70,    71,    72,    73,    74,    75,     0,    76,    77,
+       0,     0,     0,    78,    79,    80,    81,     0,   132,    82,
+     133,     0,     0,    83,    70,    71,    72,    73,    74,    75,
+      85,    76,    77,     0,     0,     0,    78,    79,    80,    81,
+       0,   134,    82,   135,     0,     0,    83,    70,    71,    72,
+      73,    74,    75,    85,    76,    77,     0,     0,     0,    78,
+      79,    80,    81,     0,     0,    82,     0,     0,     0,    83,
+       0,     0,     0,     0,     0,    94,    85,    70,    71,    72,
+      73,    74,    75,     0,    76,    77,     0,     0,     0,    78,
+      79,    80,    81,     0,     0,    82,     0,     0,     0,    83,
+       0,     0,   116,     0,     0,     0,    85,    70,    71,    72,
+      73,    74,    75,     0,    76,    77,     0,     0,     0,    78,
+      79,    80,    81,     0,     0,    82,     0,     0,     0,    83,
+       0,     0,   117,     0,     0,     0,    85,    70,    71,    72,
+      73,    74,    75,     0,    76,    77,     0,     0,     0,    78,
+      79,    80,    81,     0,   118,    82,     0,     0,     0,    83,
+      70,    71,    72,    73,    74,    75,    85,    76,    77,     0,
+       0,     0,    78,    79,    80,    81,     0,     0,    82,   124,
+       0,     0,    83,    70,    71,    72,    73,    74,    75,    85,
+      76,    77,     0,     0,     0,    78,    79,    80,    81,     0,
+       0,    82,     0,     0,     0,    83,     0,     0,     0,     0,
+       0,   125,    85,    70,    71,    72,    73,    74,    75,     0,
+      76,    77,     0,     0,     0,    78,    79,    80,    81,     0,
+       0,    82,     0,     0,     0,    83,     0,     0,     0,   136,
+       0,     0,    85,    70,    71,    72,    73,    74,    75,     0,
+      76,    77,     0,     0,     0,    78,    79,    80,    81,     0,
+       0,    82,     0,     0,     0,    83,     0,     0,   140,     0,
+       0,     0,    85,    70,    71,    72,    73,    74,    75,     0,
+      76,    77,     0,     0,     0,    78,    79,    80,    81,     0,
+       0,    82,     0,     0,     0,    83,     0,     0,   141,     0,
+       0,     0,    85,    70,    71,    72,    73,    74,    75,     0,
+      76,    77,     0,   142,     0,    78,    79,    80,    81,     0,
+       0,    82,     0,     0,     0,    83,    70,    71,    72,    73,
+      74,    75,    85,    76,    77,     0,     0,     0,    78,    79,
+      80,    81,     0,     0,    82,     0,     0,     0,    83,     0,
+     143,     0,     0,     0,     0,    85,    70,    71,    72,    73,
+      74,    75,     0,    76,    77,     0,     0,     0,    78,    79,
+      80,    81,     0,     0,    82,     0,     0,     0,    83,     0,
+     149,     0,     0,     0,     0,    85,    70,    71,    72,    73,
+      74,    75,     0,    76,    77,     0,     0,     0,    78,    79,
+      80,    81,     0,   150,    82,     0,     0,     0,    83,    70,
+      71,    72,    73,    74,    75,    85,    76,    77,     0,     0,
+       0,    78,    79,    80,    81,     0,   151,    82,     0,     0,
+       0,    83,    70,    71,    72,    73,    74,    75,    85,    76,
+      77,     0,     0,     0,    78,    79,    80,    81,     0,     0,
+      82,     0,     0,     0,    83,    70,    71,    72,    73,    74,
+      75,    85,    76,     0,     0,     0,     0,    78,    79,    80,
+      81,     0,     0,    82,     0,     0,     0,    83,    70,    71,
+      72,    73,     0,     0,     0,     0,     0,     0,     0,     0,
+      78,    79,    80,    81,     0,     0,    82,     0,     0,     0,
+      83
 };
 
 static const yytype_int16 yycheck[] =
 {
        4,     5,     6,     4,     8,     9,    10,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    43,    44,
-      24,    48,    47,    27,    28,    29,    51,    54,    30,    50,
-      34,    41,    42,    43,    44,    47,     6,    47,    45,    51,
-      45,    51,    45,    52,     0,     6,     4,    47,   123,    50,
-      54,    55,    50,    57,    53,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    66,    67,    68,    69,    70,    71,    72,    73,
-      74,    75,    76,    77,    78,    79,    -1,    81,    80,    83,
-      -1,    -1,    -1,    -1,    -1,    89,    90,    -1,    92,    93,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    29,    30,    31,    32,    33,    34,    -1,   112,   113,
-     114,   115,     4,    41,    42,    43,    44,   121,   122,    47,
-      -1,    -1,    -1,    51,    -1,    -1,    -1,    -1,   132,    -1,
-      -1,    -1,   136,   137,   138,   139,    -1,    29,    30,    31,
-      32,    33,    34,    -1,    36,    37,    -1,    -1,    -1,    41,
-      42,    43,    44,    -1,    -1,    47,    -1,    -1,    -1,    51,
-      -1,    -1,    54,    -1,     3,    -1,    58,     6,     7,     8,
-       9,    10,    11,    -1,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      -1,    -1,    -1,    -1,    -1,    -1,    35,    -1,    -1,    38,
-      -1,    40,    -1,    42,    -1,    -1,    45,    -1,    47,    -1,
-      -1,     3,    -1,    52,     6,     7,     8,     9,    10,    11,
-      -1,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    -1,    -1,    -1,
-      -1,    -1,    -1,    35,    -1,    -1,    38,    -1,    40,    -1,
-      42,    -1,    -1,    45,    -1,    47,    -1,    -1,    -1,    -1,
-      52,    29,    30,    31,    32,    33,    34,    -1,    36,    37,
-      -1,    -1,    -1,    41,    42,    43,    44,    -1,    46,    47,
-      -1,    -1,    -1,    51,    -1,    -1,    -1,    -1,    -1,    57,
-      58,    29,    30,    31,    32,    33,    34,    -1,    36,    37,
-      -1,    -1,    -1,    41,    42,    43,    44,    -1,    46,    47,
-      48,    -1,    -1,    51,    29,    30,    31,    32,    33,    34,
-      58,    36,    37,    -1,    -1,    -1,    41,    42,    43,    44,
-      -1,    46,    47,    48,    -1,    -1,    51,    29,    30,    31,
-      32,    33,    34,    58,    36,    37,    -1,    -1,    -1,    41,
-      42,    43,    44,    -1,    -1,    47,    -1,    -1,    -1,    51,
-      -1,    -1,    -1,    -1,    56,    -1,    58,    29,    30,    31,
-      32,    33,    34,    -1,    36,    37,    -1,    -1,    -1,    41,
-      42,    43,    44,    -1,    -1,    47,    -1,    -1,    -1,    51,
-      -1,    -1,    -1,    -1,    -1,    57,    58,    29,    30,    31,
-      32,    33,    34,    -1,    36,    37,    -1,    -1,    -1,    41,
-      42,    43,    44,    -1,    -1,    47,    -1,    -1,    -1,    51,
-      -1,    -1,    54,    -1,    -1,    -1,    58,    29,    30,    31,
-      32,    33,    34,    -1,    36,    37,    -1,    -1,    -1,    41,
-      42,    43,    44,    -1,    -1,    47,    -1,    -1,    -1,    51,
-      -1,    -1,    54,    -1,    -1,    -1,    58,    29,    30,    31,
-      32,    33,    34,    -1,    36,    37,    -1,    -1,    -1,    41,
-      42,    43,    44,    -1,    46,    47,    -1,    -1,    -1,    51,
-      29,    30,    31,    32,    33,    34,    58,    36,    37,    -1,
-      -1,    -1,    41,    42,    43,    44,    -1,    -1,    47,    48,
-      -1,    -1,    51,    29,    30,    31,    32,    33,    34,    58,
-      36,    37,    -1,    -1,    -1,    41,    42,    43,    44,    -1,
-      -1,    47,    -1,    -1,    -1,    51,    -1,    -1,    -1,    -1,
-      -1,    57,    58,    29,    30,    31,    32,    33,    34,    -1,
-      36,    37,    -1,    -1,    -1,    41,    42,    43,    44,    -1,
-      -1,    47,    -1,    -1,    -1,    51,    -1,    -1,    -1,    55,
-      -1,    -1,    58,    29,    30,    31,    32,    33,    34,    -1,
-      36,    37,    -1,    -1,    -1,    41,    42,    43,    44,    -1,
-      -1,    47,    -1,    -1,    -1,    51,    -1,    -1,    54,    -1,
-      -1,    -1,    58,    29,    30,    31,    32,    33,    34,    -1,
-      36,    37,    -1,    -1,    -1,    41,    42,    43,    44,    -1,
-      -1,    47,    -1,    -1,    -1,    51,    -1,    -1,    54,    -1,
-      -1,    -1,    58,    29,    30,    31,    32,    33,    34,    -1,
-      36,    37,    -1,    39,    -1,    41,    42,    43,    44,    -1,
-      -1,    47,    -1,    -1,    -1,    51,    29,    30,    31,    32,
-      33,    34,    58,    36,    37,    -1,    -1,    -1,    41,    42,
-      43,    44,    -1,    -1,    47,    -1,    -1,    -1,    51,    -1,
-      53,    -1,    -1,    -1,    -1,    58,    29,    30,    31,    32,
-      33,    34,    -1,    36,    37,    -1,    -1,    -1,    41,    42,
-      43,    44,    -1,    -1,    47,    -1,    -1,    -1,    51,    -1,
-      53,    -1,    -1,    -1,    -1,    58,    29,    30,    31,    32,
-      33,    34,    -1,    36,    37,    -1,    -1,    -1,    41,    42,
-      43,    44,    -1,    46,    47,    -1,    -1,    -1,    51,    29,
-      30,    31,    32,    33,    34,    58,    36,    37,    -1,    -1,
-      -1,    41,    42,    43,    44,    -1,    46,    47,    -1,    -1,
-      -1,    51,    29,    30,    31,    32,    33,    34,    58,    36,
-      37,    -1,    -1,    -1,    41,    42,    43,    44,    -1,    -1,
-      47,    -1,    -1,    -1,    51,    29,    30,    31,    32,    33,
-      34,    58,    36,    -1,    -1,    -1,    -1,    41,    42,    43,
-      44,    -1,    -1,    47,    -1,    -1,    -1,    51,    29,    30,
-      31,    32,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      41,    42,    43,    44,    -1,    -1,    47,    -1,    -1,    -1,
-      51
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      45,    46,    26,    50,    49,    29,    30,    31,    53,    56,
+      32,    52,    36,     6,    31,    32,    33,    34,    35,    36,
+      49,    38,    39,    54,    53,     0,    43,    44,    45,    46,
+      49,    52,    49,    47,    58,    59,    53,    61,    47,    47,
+      52,    58,     6,    60,    55,     4,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+     127,    85,    84,    87,    -1,    43,    44,    45,    46,    93,
+      94,    49,    96,    97,    -1,    53,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    31,    32,    33,    34,    35,
+      36,    -1,   116,   117,   118,   119,     4,    43,    44,    45,
+      46,   125,   126,    49,    -1,    -1,    -1,    53,    -1,    -1,
+      -1,    -1,   136,    -1,    -1,    -1,   140,   141,   142,   143,
+      -1,    -1,    -1,    31,    32,    33,    34,    35,    36,    -1,
+      38,    39,    -1,    -1,    -1,    43,    44,    45,    46,    -1,
+      -1,    49,    -1,    -1,    -1,    53,    -1,    -1,    56,    -1,
+       3,    -1,    60,     6,     7,     8,     9,    10,    11,    -1,
+      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    -1,    -1,
+      -1,    -1,    -1,    -1,    37,    -1,    -1,    40,    -1,    42,
+      -1,    44,    -1,    -1,    47,    -1,    49,    -1,    -1,     3,
+      -1,    54,     6,     7,     8,     9,    10,    11,    -1,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    -1,    -1,    -1,
+      -1,    -1,    -1,    37,    -1,    -1,    40,    -1,    42,    -1,
+      44,    -1,    -1,    47,    -1,    49,    -1,    -1,    -1,    -1,
+      54,    31,    32,    33,    34,    35,    36,    -1,    38,    39,
+      -1,    -1,    -1,    43,    44,    45,    46,    -1,    48,    49,
+      -1,    -1,    -1,    53,    -1,    -1,    -1,    -1,    -1,    59,
+      60,    31,    32,    33,    34,    35,    36,    -1,    38,    39,
+      -1,    -1,    -1,    43,    44,    45,    46,    -1,    48,    49,
+      50,    -1,    -1,    53,    31,    32,    33,    34,    35,    36,
+      60,    38,    39,    -1,    -1,    -1,    43,    44,    45,    46,
+      -1,    48,    49,    50,    -1,    -1,    53,    31,    32,    33,
+      34,    35,    36,    60,    38,    39,    -1,    -1,    -1,    43,
+      44,    45,    46,    -1,    -1,    49,    -1,    -1,    -1,    53,
+      -1,    -1,    -1,    -1,    -1,    59,    60,    31,    32,    33,
+      34,    35,    36,    -1,    38,    39,    -1,    -1,    -1,    43,
+      44,    45,    46,    -1,    -1,    49,    -1,    -1,    -1,    53,
+      -1,    -1,    56,    -1,    -1,    -1,    60,    31,    32,    33,
+      34,    35,    36,    -1,    38,    39,    -1,    -1,    -1,    43,
+      44,    45,    46,    -1,    -1,    49,    -1,    -1,    -1,    53,
+      -1,    -1,    56,    -1,    -1,    -1,    60,    31,    32,    33,
+      34,    35,    36,    -1,    38,    39,    -1,    -1,    -1,    43,
+      44,    45,    46,    -1,    48,    49,    -1,    -1,    -1,    53,
+      31,    32,    33,    34,    35,    36,    60,    38,    39,    -1,
+      -1,    -1,    43,    44,    45,    46,    -1,    -1,    49,    50,
+      -1,    -1,    53,    31,    32,    33,    34,    35,    36,    60,
+      38,    39,    -1,    -1,    -1,    43,    44,    45,    46,    -1,
+      -1,    49,    -1,    -1,    -1,    53,    -1,    -1,    -1,    -1,
+      -1,    59,    60,    31,    32,    33,    34,    35,    36,    -1,
+      38,    39,    -1,    -1,    -1,    43,    44,    45,    46,    -1,
+      -1,    49,    -1,    -1,    -1,    53,    -1,    -1,    -1,    57,
+      -1,    -1,    60,    31,    32,    33,    34,    35,    36,    -1,
+      38,    39,    -1,    -1,    -1,    43,    44,    45,    46,    -1,
+      -1,    49,    -1,    -1,    -1,    53,    -1,    -1,    56,    -1,
+      -1,    -1,    60,    31,    32,    33,    34,    35,    36,    -1,
+      38,    39,    -1,    -1,    -1,    43,    44,    45,    46,    -1,
+      -1,    49,    -1,    -1,    -1,    53,    -1,    -1,    56,    -1,
+      -1,    -1,    60,    31,    32,    33,    34,    35,    36,    -1,
+      38,    39,    -1,    41,    -1,    43,    44,    45,    46,    -1,
+      -1,    49,    -1,    -1,    -1,    53,    31,    32,    33,    34,
+      35,    36,    60,    38,    39,    -1,    -1,    -1,    43,    44,
+      45,    46,    -1,    -1,    49,    -1,    -1,    -1,    53,    -1,
+      55,    -1,    -1,    -1,    -1,    60,    31,    32,    33,    34,
+      35,    36,    -1,    38,    39,    -1,    -1,    -1,    43,    44,
+      45,    46,    -1,    -1,    49,    -1,    -1,    -1,    53,    -1,
+      55,    -1,    -1,    -1,    -1,    60,    31,    32,    33,    34,
+      35,    36,    -1,    38,    39,    -1,    -1,    -1,    43,    44,
+      45,    46,    -1,    48,    49,    -1,    -1,    -1,    53,    31,
+      32,    33,    34,    35,    36,    60,    38,    39,    -1,    -1,
+      -1,    43,    44,    45,    46,    -1,    48,    49,    -1,    -1,
+      -1,    53,    31,    32,    33,    34,    35,    36,    60,    38,
+      39,    -1,    -1,    -1,    43,    44,    45,    46,    -1,    -1,
+      49,    -1,    -1,    -1,    53,    31,    32,    33,    34,    35,
+      36,    60,    38,    -1,    -1,    -1,    -1,    43,    44,    45,
+      46,    -1,    -1,    49,    -1,    -1,    -1,    53,    31,    32,
+      33,    34,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      43,    44,    45,    46,    -1,    -1,    49,    -1,    -1,    -1,
+      53
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -840,19 +845,20 @@
 {
        0,     3,     6,     7,     8,     9,    10,    11,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    35,    38,    40,    42,    45,    47,
-      52,    60,    61,    62,    50,    62,    62,    62,     6,    63,
-      62,    62,    62,    62,    62,    62,    62,    62,    62,    62,
-      62,    62,    62,    62,    45,    45,    62,    45,    52,    62,
-      62,    62,    64,     6,    61,     0,    29,    30,    31,    32,
-      33,    34,    36,    37,    41,    42,    43,    44,    47,    51,
-      56,    58,    62,    50,    62,    62,    62,     6,    46,    57,
-      57,    48,    54,     4,    53,    62,    62,    62,    62,    62,
-      62,    62,    62,    62,    62,    62,    62,    62,    62,    61,
-      62,    62,    54,    54,    46,     4,    62,    62,    62,    62,
-      48,    57,     4,    54,    62,    62,    62,    62,    46,    48,
-      46,    48,    55,    62,    62,    63,    54,    54,    39,    53,
-      62,    62,    62,    62,    62,    53,    46,    46
+      25,    26,    27,    28,    29,    30,    37,    40,    42,    44,
+      47,    49,    54,    62,    63,    64,    52,    64,    64,    64,
+       6,    65,    64,    64,    64,    64,    64,    64,    64,    64,
+      64,    64,    64,    64,    64,    64,    64,    64,    47,    47,
+      64,    47,    54,    64,    64,    64,    66,     6,    63,     0,
+      31,    32,    33,    34,    35,    36,    38,    39,    43,    44,
+      45,    46,    49,    53,    58,    60,    64,    52,    64,    64,
+      64,     6,    48,    59,    59,    50,    56,     4,    55,    64,
+      64,    64,    64,    64,    64,    64,    64,    64,    64,    64,
+      64,    64,    64,    63,    64,    64,    56,    56,    48,     4,
+      64,    64,    64,    64,    50,    59,     4,    56,    64,    64,
+      64,    64,    48,    50,    48,    50,    57,    64,    64,    65,
+      56,    56,    41,    55,    64,    64,    64,    64,    64,    55,
+      48,    48
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -2052,15 +2058,35 @@
 #line 295 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
-        (yyval.node)->type = NODETYPE_ISNAN;
-        (yyval.node)->flags |= ALLARGS_SCALAR;
+        (yyval.node)->type = NODETYPE_IMAX;
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
   case 39:
 
 /* Line 1455 of yacc.c  */
-#line 302 "gram.y"
+#line 301 "gram.y"
+    { (yyval.node) = new_scalar_node(1);
+        (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
+        (yyval.node)->type = NODETYPE_IMIN;
+        (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
+    break;
+
+  case 40:
+
+/* Line 1455 of yacc.c  */
+#line 307 "gram.y"
+    { (yyval.node) = new_scalar_node(1);
+        (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
+        (yyval.node)->type = NODETYPE_ISNAN;
+        (yyval.node)->flags |= ALLARGS_SCALAR;
+        (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
+    break;
+
+  case 41:
+
+/* Line 1455 of yacc.c  */
+#line 314 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
         (yyval.node)->type = NODETYPE_SQRT;
@@ -2068,10 +2094,10 @@
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
-  case 40:
+  case 42:
 
 /* Line 1455 of yacc.c  */
-#line 309 "gram.y"
+#line 321 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
         (yyval.node)->type = NODETYPE_ABS;
@@ -2079,10 +2105,10 @@
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
-  case 41:
+  case 43:
 
 /* Line 1455 of yacc.c  */
-#line 316 "gram.y"
+#line 328 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
         (yyval.node)->type = NODETYPE_EXP;
@@ -2090,10 +2116,10 @@
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
-  case 42:
+  case 44:
 
 /* Line 1455 of yacc.c  */
-#line 323 "gram.y"
+#line 335 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
         (yyval.node)->type = NODETYPE_LOG;
@@ -2101,10 +2127,10 @@
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
-  case 43:
+  case 45:
 
 /* Line 1455 of yacc.c  */
-#line 330 "gram.y"
+#line 342 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
         (yyval.node)->type = NODETYPE_SIN;
@@ -2112,10 +2138,10 @@
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
-  case 44:
+  case 46:
 
 /* Line 1455 of yacc.c  */
-#line 337 "gram.y"
+#line 349 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
         (yyval.node)->type = NODETYPE_COS;
@@ -2123,10 +2149,10 @@
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
-  case 45:
+  case 47:
 
 /* Line 1455 of yacc.c  */
-#line 344 "gram.y"
+#line 356 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
         (yyval.node)->type = NODETYPE_TAN;
@@ -2134,10 +2160,10 @@
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
-  case 46:
+  case 48:
 
 /* Line 1455 of yacc.c  */
-#line 351 "gram.y"
+#line 363 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
         (yyval.node)->type = NODETYPE_ASIN;
@@ -2145,10 +2171,10 @@
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
-  case 47:
+  case 49:
 
 /* Line 1455 of yacc.c  */
-#line 358 "gram.y"
+#line 370 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
         (yyval.node)->type = NODETYPE_ACOS;
@@ -2156,10 +2182,10 @@
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
-  case 48:
+  case 50:
 
 /* Line 1455 of yacc.c  */
-#line 365 "gram.y"
+#line 377 "gram.y"
     { (yyval.node) = new_scalar_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (2)].pos);
         (yyval.node)->type = NODETYPE_ATAN;
@@ -2167,10 +2193,10 @@
         (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); }
     break;
 
-  case 49:
+  case 51:
 
 /* Line 1455 of yacc.c  */
-#line 372 "gram.y"
+#line 384 "gram.y"
     { (yyval.node) = new_scalar_node(3);
         (yyval.node)->pos = (yyvsp[(1) - (8)].pos);
         (yyval.node)->type = NODETYPE_CLAMP;
@@ -2180,10 +2206,10 @@
         (yyval.node)->expr[2] = (yyvsp[(7) - (8)].node); }
     break;
 
-  case 50:
+  case 52:
 
 /* Line 1455 of yacc.c  */
-#line 381 "gram.y"
+#line 393 "gram.y"
     { (yyval.node) = new_scalar_node(3);
         (yyval.node)->pos = (yyvsp[(1) - (8)].pos);
         (yyval.node)->type = NODETYPE_SEGMENT;
@@ -2193,10 +2219,10 @@
         (yyval.node)->expr[2] = (yyvsp[(7) - (8)].node); }
     break;
 
-  case 51:
+  case 53:
 
 /* Line 1455 of yacc.c  */
-#line 390 "gram.y"
+#line 402 "gram.y"
     { (yyval.node) = new_node(3, node_is_scalar((yyvsp[(3) - (5)].node)));
         (yyval.node)->pos = (yyvsp[(2) - (5)].pos);
         (yyval.node)->type = NODETYPE_IFELSE;
@@ -2205,10 +2231,10 @@
         (yyval.node)->expr[2] = (yyvsp[(5) - (5)].node); }
     break;
 
-  case 52:
+  case 54:
 
 /* Line 1455 of yacc.c  */
-#line 398 "gram.y"
+#line 410 "gram.y"
     { (yyval.node) = new_node(3, node_is_scalar((yyvsp[(5) - (7)].node)));
         (yyval.node)->pos = (yyvsp[(1) - (7)].pos);
         (yyval.node)->type = NODETYPE_IFELSE;
@@ -2217,10 +2243,10 @@
         (yyval.node)->expr[2] = (yyvsp[(7) - (7)].node); }
     break;
 
-  case 53:
+  case 55:
 
 /* Line 1455 of yacc.c  */
-#line 406 "gram.y"
+#line 418 "gram.y"
     { (yyval.node) = new_node(2, node_is_scalar((yyvsp[(5) - (5)].node)));
         (yyval.node)->pos = (yyvsp[(1) - (5)].pos);
         (yyval.node)->type = NODETYPE_IFELSE;
@@ -2228,10 +2254,10 @@
         (yyval.node)->expr[1] = (yyvsp[(5) - (5)].node); }
     break;
 
-  case 54:
+  case 56:
 
 /* Line 1455 of yacc.c  */
-#line 413 "gram.y"
+#line 425 "gram.y"
     { (yyval.node) = new_scalar_node(2);
         (yyval.node)->pos = (yyvsp[(1) - (7)].pos);
         (yyval.node)->type = NODETYPE_FOR;
@@ -2240,40 +2266,40 @@
         (yyval.node)->expr[1] = (yyvsp[(7) - (7)].node); }
     break;
 
-  case 55:
+  case 57:
 
 /* Line 1455 of yacc.c  */
-#line 421 "gram.y"
+#line 433 "gram.y"
     { (yyval.node) = new_node(0, ident_is_scalar((yyvsp[(1) - (1)].ident)));
         (yyval.node)->type = NODETYPE_IDENT;
         (yyval.node)->pos = -1;
         (yyval.node)->ident = (yyvsp[(1) - (1)].ident); }
     break;
 
-  case 56:
+  case 58:
 
 /* Line 1455 of yacc.c  */
-#line 427 "gram.y"
+#line 439 "gram.y"
     { (yyval.node) = new_scalar_node(0);
         (yyval.node)->pos = -1;
         (yyval.node)->type = NODETYPE_REAL;
         (yyval.node)->real = (yyvsp[(1) - (1)].real); }
     break;
 
-  case 57:
+  case 59:
 
 /* Line 1455 of yacc.c  */
-#line 433 "gram.y"
+#line 445 "gram.y"
     { (yyval.node) = new_scalar_node(0);
         (yyval.node)->pos = -1;
         (yyval.node)->type = NODETYPE_REAL;
         (yyval.node)->real = INVALID_VALUE; }
     break;
 
-  case 58:
+  case 60:
 
 /* Line 1455 of yacc.c  */
-#line 442 "gram.y"
+#line 454 "gram.y"
     { (yyval.node) = new_scalar_node(2);
         (yyval.node)->type = NODETYPE_LET;
         (yyval.node)->pos = (yyvsp[(2) - (5)].pos);
@@ -2282,10 +2308,10 @@
         (yyval.node)->expr[1] = (yyvsp[(5) - (5)].node); }
     break;
 
-  case 59:
+  case 61:
 
 /* Line 1455 of yacc.c  */
-#line 449 "gram.y"
+#line 461 "gram.y"
     { (yyval.node) = new_scalar_node(2);
         (yyval.node)->pos = (yyvsp[(2) - (5)].pos);
         (yyval.node)->type = NODETYPE_LET;
@@ -2294,20 +2320,20 @@
         (yyval.node)->expr[1] = (yyvsp[(5) - (5)].node); }
     break;
 
-  case 60:
+  case 62:
 
 /* Line 1455 of yacc.c  */
-#line 458 "gram.y"
+#line 470 "gram.y"
     { (yyval.node) = new_vector_node(1);
         (yyval.node)->pos = (yyvsp[(1) - (1)].node)->pos;
         (yyval.node)->type = NODETYPE_VEC1;
         (yyval.node)->expr[0] = (yyvsp[(1) - (1)].node); }
     break;
 
-  case 61:
+  case 63:
 
 /* Line 1455 of yacc.c  */
-#line 463 "gram.y"
+#line 475 "gram.y"
     { (yyval.node) = new_vector_node(2);
         (yyval.node)->pos = (yyvsp[(2) - (3)].pos);
         (yyval.node)->type = NODETYPE_VEC2;
@@ -2318,7 +2344,7 @@
 
 
 /* Line 1455 of yacc.c  */
-#line 2322 "progs/minccalc/gram.c"
+#line 2348 "progs/minccalc/gram.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2530,7 +2556,7 @@
 
 
 /* Line 1675 of yacc.c  */
-#line 470 "gram.y"
+#line 482 "gram.y"
 
 
 node_t root;
--- a/progs/minccalc/gram.y
+++ b/progs/minccalc/gram.y
@@ -20,7 +20,7 @@
 }
 
 %token      NAN
-%token      IN TO IDENT REAL AVG PROD SUM LET NEG LEN MAX MIN
+%token      IN TO IDENT REAL AVG PROD SUM LET NEG LEN MAX MIN IMAX IMIN
 %token      ISNAN SQRT ABS EXP LOG SIN COS TAN ASIN ACOS ATAN CLAMP SEGMENT
 %token      LT LE GT GE EQ NE NOT AND OR
 %token      IF ELSE FOR
@@ -28,7 +28,7 @@
 %type<ident>   IDENT 
 %type<real>    REAL
 %type<pos>     IN TO AVG SUM PROD LET NEG LEN IF ELSE FOR
-%type<pos>     ISNAN SQRT ABS MAX MIN EXP LOG SIN COS TAN ASIN ACOS ATAN
+%type<pos>     ISNAN SQRT ABS MAX MIN IMAX IMIN EXP LOG SIN COS TAN ASIN ACOS ATAN
 %type<pos>     CLAMP SEGMENT
 %type<pos>     NOT LT LE GT GE EQ NE AND OR
 %type<pos>     '+' '-' '*' '/' '(' ')' '[' ']' '.' '=' '^' '{' '}' ',' '|' ';'
@@ -46,7 +46,7 @@
 %left    '*' '/'
 %right   NEG NOT
 %right   '^'
-%right   AVG SUM PROD LEN ISNAN SQRT ABS MAX MIN EXP LOG SIN COS TAN ASIN ACOS ATAN
+%right   AVG SUM PROD LEN ISNAN SQRT ABS MAX MIN IMAX IMIN EXP LOG SIN COS TAN ASIN ACOS ATAN
 
 %%
 
@@ -291,6 +291,18 @@
         $$->type = NODETYPE_MIN;
         $$->expr[0] = $2; }
 
+   |   IMAX expr
+      { $$ = new_scalar_node(1);
+        $$->pos = $1;
+        $$->type = NODETYPE_IMAX;
+        $$->expr[0] = $2; }
+
+   |   IMIN expr
+      { $$ = new_scalar_node(1);
+        $$->pos = $1;
+        $$->type = NODETYPE_IMIN;
+        $$->expr[0] = $2; }
+
    |   ISNAN expr
       { $$ = new_scalar_node(1);
         $$->pos = $1;
--- a/progs/minccalc/lex.c
+++ b/progs/minccalc/lex.c
@@ -1,6 +1,5 @@
-#line 2 "minccalc/lex.c"
 
-#line 4 "minccalc/lex.c"
+#line 3 "progs/minccalc/lex.c"
 
 #define  YY_INT_ALIGNED short int
 
@@ -9,7 +8,7 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 33
+#define YY_FLEX_SUBMINOR_VERSION 35
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -31,7 +30,7 @@
 
 /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 
-#if __STDC_VERSION__ >= 199901L
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 
 /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
  * if you want the limit (max/min) macros for int types. 
@@ -54,7 +53,6 @@
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -85,6 +83,8 @@
 #define UINT32_MAX             (4294967295U)
 #endif
 
+#endif /* ! C99 */
+
 #endif /* ! FLEXINT_H */
 
 #ifdef __cplusplus
@@ -94,11 +94,12 @@
 
 #else	/* ! __cplusplus */
 
-#if __STDC__
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
 
 #define YY_USE_CONST
 
-#endif	/* __STDC__ */
+#endif	/* defined (__STDC__) */
 #endif	/* ! __cplusplus */
 
 #ifdef YY_USE_CONST
@@ -140,7 +141,15 @@
 
 /* Size of default input buffer. */
 #ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
 #define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
 #endif
 
 /* The state buf must be large enough to hold one state per character in the main buffer.
@@ -178,14 +187,9 @@
 
 #define unput(c) yyunput( c, (yytext_ptr)  )
 
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-
 #ifndef YY_TYPEDEF_YY_SIZE_T
 #define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int yy_size_t;
+typedef size_t yy_size_t;
 #endif
 
 #ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -364,8 +368,8 @@
 	*yy_cp = '\0'; \
 	(yy_c_buf_p) = yy_cp;
 
-#define YY_NUM_RULES 40
-#define YY_END_OF_BUFFER 41
+#define YY_NUM_RULES 42
+#define YY_END_OF_BUFFER 43
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -373,20 +377,20 @@
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[103] =
+static yyconst flex_int16_t yy_accept[108] =
     {   0,
-        0,    0,   41,   39,   38,   38,   33,   39,   37,   27,
-       39,   29,   36,   36,   36,   36,   36,   36,   36,   36,
-       36,   36,   36,   36,   39,   38,   32,   34,   37,   37,
-        0,   28,   31,   30,   36,   36,   36,   36,   36,   36,
-       36,   36,   36,   36,   36,   36,   23,   21,   36,   36,
-       36,   36,   36,   36,   36,   36,   36,   36,   36,   22,
-       35,   37,    0,   37,   26,    8,   36,   36,   36,    1,
-       36,   14,   36,   11,   25,   36,    5,    4,   12,    9,
-       10,   36,   36,   13,   36,    2,   15,   17,   16,   18,
-       36,   24,   36,    3,   36,    7,   19,    6,   36,   36,
+        0,    0,   43,   41,   40,   40,   35,   41,   39,   29,
+       41,   31,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   41,   40,   34,   36,   39,   39,
+        0,   30,   33,   32,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   25,   38,   23,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       24,   37,   39,    0,   39,   28,    8,   38,   38,   38,
+        1,   38,   16,   38,   13,   27,   38,   38,   38,    5,
+        4,   14,    9,   10,   38,   38,   15,   38,    2,   17,
+       19,   18,   20,   38,   26,   11,   12,   38,    3,   38,
 
-       20,    0
+        7,   21,    6,   38,   38,   22,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -429,80 +433,82 @@
         2,    2,    2,    2,    2,    1
     } ;
 
-static yyconst flex_int16_t yy_base[104] =
+static yyconst flex_int16_t yy_base[109] =
     {   0,
-        0,    0,  130,  131,   35,   37,  119,  123,   34,  117,
-      116,  115,    0,  108,   26,   21,   26,   96,   25,   32,
-       39,   92,   43,   37,   85,   65,  131,  131,   57,   66,
-       63,  131,  131,  131,    0,  106,   88,   91,   94,  100,
-       93,   98,   82,   81,   83,   80,    0,    0,   83,   49,
-       86,   72,   80,   78,   82,   77,   72,   76,   74,    0,
-      131,   70,   91,   90,    0,    0,   66,   70,   69,    0,
-       69,    0,   73,    0,    0,   76,    0,    0,    0,    0,
-        0,   72,   64,    0,   56,    0,    0,    0,    0,    0,
-       59,    0,   59,    0,   64,    0,    0,    0,   56,   48,
+        0,    0,  135,  136,   35,   37,  124,  128,   34,  122,
+      121,  120,    0,  113,   26,   21,   26,  101,   38,   26,
+       33,   97,   42,   39,   90,   49,  136,  136,   59,   69,
+       62,  136,  136,  136,    0,  111,   93,   96,   99,  105,
+       98,  103,   87,   86,   88,   85,    0,   57,    0,   88,
+       52,   91,   77,   85,   83,   87,   82,   77,   81,   79,
+        0,  136,   73,   96,   95,    0,    0,   71,   75,   74,
+        0,   74,    0,   78,    0,    0,   62,   70,   79,    0,
+        0,    0,    0,    0,   75,   67,    0,   59,    0,    0,
+        0,    0,    0,   62,    0,    0,    0,   62,    0,   67,
 
-        0,  131,   47
+        0,    0,    0,   59,   51,    0,  136,   72
     } ;
 
-static yyconst flex_int16_t yy_def[104] =
+static yyconst flex_int16_t yy_def[109] =
     {   0,
-      102,    1,  102,  102,  102,  102,  102,  102,  102,  102,
-      102,  102,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  102,  102,  102,  102,  102,  102,
-      102,  102,  102,  102,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      102,  102,  102,  102,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      107,    1,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  108,  108,  108,  108,  108,  108,  108,  108,
+      108,  108,  108,  108,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  108,  108,  108,  108,  108,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
+      108,  107,  107,  107,  107,  108,  108,  108,  108,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
 
-      103,    0,  102
+      108,  108,  108,  108,  108,  108,    0,  107
     } ;
 
-static yyconst flex_int16_t yy_nxt[168] =
+static yyconst flex_int16_t yy_nxt[173] =
     {   0,
         4,    5,    6,    7,    8,    4,    4,    9,   10,   11,
        12,   13,   13,   14,    4,   15,   13,   16,   13,   17,
        18,   13,   19,   20,   21,   13,   13,   22,   13,   13,
        23,   24,   13,   13,   13,   25,   26,   26,   26,   26,
-       29,   30,   37,   38,   42,   47,   31,   43,   35,   44,
-       48,   50,   59,   31,   52,   49,   39,   40,   51,   41,
-       45,   53,   55,   60,   62,   56,   26,   26,   63,   31,
-       64,   57,   29,   30,   77,   58,   31,   62,   31,  101,
-       78,  100,   31,   99,   98,   31,   97,   96,   95,   31,
-       94,   93,   92,   91,   90,   89,   88,   64,   64,   87,
+       29,   30,   37,   38,   42,   51,   31,   43,   53,   44,
+       26,   26,   52,   31,   60,   54,   39,   40,   47,   41,
+       45,   56,   48,   49,   57,   61,   63,   64,   50,   65,
+       58,   31,   77,   35,   59,   29,   30,   80,   31,   78,
+       63,   31,  106,   81,  105,   31,  104,  103,   31,  102,
+      101,  100,   31,   99,   98,   97,   96,   95,   94,   93,
 
-       86,   85,   84,   83,   82,   81,   80,   79,   76,   75,
-       74,   73,   72,   71,   70,   69,   68,   67,   66,   65,
-       61,   54,   46,   36,   34,   33,   32,   28,   27,  102,
-        3,  102,  102,  102,  102,  102,  102,  102,  102,  102,
-      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
-      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
-      102,  102,  102,  102,  102,  102,  102
+       92,   91,   65,   65,   90,   89,   88,   87,   86,   85,
+       84,   83,   82,   79,   76,   75,   74,   73,   72,   71,
+       70,   69,   68,   67,   66,   62,   55,   46,   36,   34,
+       33,   32,   28,   27,  107,    3,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107
     } ;
 
-static yyconst flex_int16_t yy_chk[168] =
+static yyconst flex_int16_t yy_chk[173] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    5,    5,    6,    6,
-        9,    9,   15,   15,   16,   19,    9,   16,  103,   17,
-       19,   20,   24,    9,   21,   19,   15,   15,   20,   15,
-       17,   21,   23,   24,   29,   23,   26,   26,   31,   29,
-       31,   23,   30,   30,   50,   23,   29,   62,   30,  100,
-       50,   99,   62,   95,   93,   30,   91,   85,   83,   62,
-       82,   76,   73,   71,   69,   68,   67,   64,   63,   59,
+        9,    9,   15,   15,   16,   20,    9,   16,   21,   17,
+       26,   26,   20,    9,   24,   21,   15,   15,   19,   15,
+       17,   23,   19,   19,   23,   24,   29,   31,   19,   31,
+       23,   29,   48,  108,   23,   30,   30,   51,   29,   48,
+       63,   30,  105,   51,  104,   63,  100,   98,   30,   94,
+       88,   86,   63,   85,   79,   78,   77,   74,   72,   70,
 
-       58,   57,   56,   55,   54,   53,   52,   51,   49,   46,
-       45,   44,   43,   42,   41,   40,   39,   38,   37,   36,
-       25,   22,   18,   14,   12,   11,   10,    8,    7,    3,
-      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
-      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
-      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
-      102,  102,  102,  102,  102,  102,  102
+       69,   68,   65,   64,   60,   59,   58,   57,   56,   55,
+       54,   53,   52,   50,   46,   45,   44,   43,   42,   41,
+       40,   39,   38,   37,   36,   25,   22,   18,   14,   12,
+       11,   10,    8,    7,    3,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -519,15 +525,15 @@
 #define YY_MORE_ADJ 0
 #define YY_RESTORE_YY_MORE_OFFSET
 char *yytext;
-#line 1 "minccalc/lex.l"
-#line 2 "minccalc/lex.l"
+#line 1 "lex.l"
+#line 2 "lex.l"
 #include <string.h>
 #include "node.h"
-#include "y.tab.h"
+#include "gram.h"
 
 int lexpos = 0;
 #define setpos() yylval.pos = lexpos; lexpos += yyleng
-#line 531 "minccalc/lex.c"
+#line 537 "progs/minccalc/lex.c"
 
 #define INITIAL 0
 
@@ -545,6 +551,35 @@
 
 static int yy_init_globals (void );
 
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (void );
+
+int yyget_debug (void );
+
+void yyset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE yyget_extra (void );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *yyget_in (void );
+
+void yyset_in  (FILE * in_str  );
+
+FILE *yyget_out (void );
+
+void yyset_out  (FILE * out_str  );
+
+int yyget_leng (void );
+
+char *yyget_text (void );
+
+int yyget_lineno (void );
+
+void yyset_lineno (int line_number  );
+
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
  */
@@ -579,7 +614,12 @@
 
 /* Amount of stuff to slurp up with each read. */
 #ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
 #define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
 #endif
 
 /* Copy whatever the last rule matched to the standard output. */
@@ -587,7 +627,7 @@
 /* This used to be an fputs(), but since the string might contain NUL's,
  * we now use fwrite().
  */
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
 #endif
 
 /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
@@ -680,10 +720,10 @@
 	register char *yy_cp, *yy_bp;
 	register int yy_act;
     
-#line 10 "minccalc/lex.l"
+#line 10 "lex.l"
 
 
-#line 687 "minccalc/lex.c"
+#line 727 "progs/minccalc/lex.c"
 
 	if ( !(yy_init) )
 		{
@@ -736,13 +776,13 @@
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 103 )
+				if ( yy_current_state >= 108 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			++yy_cp;
 			}
-		while ( yy_base[yy_current_state] != 131 );
+		while ( yy_base[yy_current_state] != 136 );
 
 yy_find_action:
 		yy_act = yy_accept[yy_current_state];
@@ -768,214 +808,224 @@
 
 case 1:
 YY_RULE_SETUP
-#line 12 "minccalc/lex.l"
+#line 12 "lex.l"
 setpos(); return AVG;
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 13 "minccalc/lex.l"
+#line 13 "lex.l"
 setpos(); return SUM;
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 14 "minccalc/lex.l"
+#line 14 "lex.l"
 setpos(); return PROD;
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 15 "minccalc/lex.l"
+#line 15 "lex.l"
 setpos(); return LET;
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 16 "minccalc/lex.l"
+#line 16 "lex.l"
 setpos(); return LEN;
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 17 "minccalc/lex.l"
+#line 17 "lex.l"
 setpos(); return ISNAN;
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 18 "minccalc/lex.l"
+#line 18 "lex.l"
 setpos(); return SQRT;
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 19 "minccalc/lex.l"
+#line 19 "lex.l"
 setpos(); return ABS;
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 20 "minccalc/lex.l"
+#line 20 "lex.l"
 setpos(); return MAX;
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 21 "minccalc/lex.l"
+#line 21 "lex.l"
 setpos(); return MIN;
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 22 "minccalc/lex.l"
-setpos(); return EXP;
+#line 22 "lex.l"
+setpos(); return IMAX;
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 23 "minccalc/lex.l"
-setpos(); return LOG;
+#line 23 "lex.l"
+setpos(); return IMIN;
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 24 "minccalc/lex.l"
-setpos(); return SIN;
+#line 24 "lex.l"
+setpos(); return EXP;
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 25 "minccalc/lex.l"
-setpos(); return COS;
+#line 25 "lex.l"
+setpos(); return LOG;
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 26 "minccalc/lex.l"
-setpos(); return TAN;
+#line 26 "lex.l"
+setpos(); return SIN;
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 27 "minccalc/lex.l"
-setpos(); return ASIN;
+#line 27 "lex.l"
+setpos(); return COS;
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 28 "minccalc/lex.l"
-setpos(); return ACOS;
+#line 28 "lex.l"
+setpos(); return TAN;
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 29 "minccalc/lex.l"
-setpos(); return ATAN;
+#line 29 "lex.l"
+setpos(); return ASIN;
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 30 "minccalc/lex.l"
-setpos(); return CLAMP;
+#line 30 "lex.l"
+setpos(); return ACOS;
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 31 "minccalc/lex.l"
-setpos(); return SEGMENT;
+#line 31 "lex.l"
+setpos(); return ATAN;
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 32 "minccalc/lex.l"
-setpos(); return IN;
+#line 32 "lex.l"
+setpos(); return CLAMP;
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 33 "minccalc/lex.l"
-setpos(); return TO;
+#line 33 "lex.l"
+setpos(); return SEGMENT;
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 34 "minccalc/lex.l"
-setpos(); return IF;
+#line 34 "lex.l"
+setpos(); return IN;
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 35 "minccalc/lex.l"
-setpos(); return ELSE;
+#line 35 "lex.l"
+setpos(); return TO;
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 36 "minccalc/lex.l"
-setpos(); return FOR;
+#line 36 "lex.l"
+setpos(); return IF;
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 37 "minccalc/lex.l"
-setpos(); return NAN;
+#line 37 "lex.l"
+setpos(); return ELSE;
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 38 "minccalc/lex.l"
-setpos(); return LT;
+#line 38 "lex.l"
+setpos(); return FOR;
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 39 "minccalc/lex.l"
-setpos(); return LE;
+#line 39 "lex.l"
+setpos(); return NAN;
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 40 "minccalc/lex.l"
-setpos(); return GT;
+#line 40 "lex.l"
+setpos(); return LT;
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 41 "minccalc/lex.l"
-setpos(); return GE;
+#line 41 "lex.l"
+setpos(); return LE;
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 42 "minccalc/lex.l"
-setpos(); return EQ;
+#line 42 "lex.l"
+setpos(); return GT;
 	YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 43 "minccalc/lex.l"
-setpos(); return NE;
+#line 43 "lex.l"
+setpos(); return GE;
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 44 "minccalc/lex.l"
-setpos(); return NOT;
+#line 44 "lex.l"
+setpos(); return EQ;
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 45 "minccalc/lex.l"
-setpos(); return AND;
+#line 45 "lex.l"
+setpos(); return NE;
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 46 "minccalc/lex.l"
-setpos(); return OR;
+#line 46 "lex.l"
+setpos(); return NOT;
 	YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 47 "minccalc/lex.l"
+#line 47 "lex.l"
+setpos(); return AND;
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 48 "lex.l"
+setpos(); return OR;
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 49 "lex.l"
 {
                   setpos();
                   yylval.ident = new_ident(yytext); 
                   return IDENT; 
                }
 	YY_BREAK
-case 37:
+case 39:
 YY_RULE_SETUP
-#line 52 "minccalc/lex.l"
+#line 54 "lex.l"
 {
                   setpos();
                   yylval.real = atof(yytext);;
                   return REAL;
                }
 	YY_BREAK
-case 38:
-/* rule 38 can match eol */
+case 40:
+/* rule 40 can match eol */
 YY_RULE_SETUP
-#line 57 "minccalc/lex.l"
+#line 59 "lex.l"
 setpos();
 	YY_BREAK
-case 39:
+case 41:
 YY_RULE_SETUP
-#line 58 "minccalc/lex.l"
+#line 60 "lex.l"
 setpos(); return yytext[0];
 	YY_BREAK
-case 40:
+case 42:
 YY_RULE_SETUP
-#line 61 "minccalc/lex.l"
+#line 63 "lex.l"
 ECHO;
 	YY_BREAK
-#line 979 "minccalc/lex.c"
+#line 1029 "progs/minccalc/lex.c"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -1230,6 +1280,14 @@
 	else
 		ret_val = EOB_ACT_CONTINUE_SCAN;
 
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
 	(yy_n_chars) += number_to_move;
 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
@@ -1259,7 +1317,7 @@
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 103 )
+			if ( yy_current_state >= 108 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1287,11 +1345,11 @@
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 103 )
+		if ( yy_current_state >= 108 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 102);
+	yy_is_jam = (yy_current_state == 107);
 
 	return yy_is_jam ? 0 : yy_current_state;
 }
@@ -1645,7 +1703,9 @@
 		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
 								(num_to_alloc * sizeof(struct yy_buffer_state*)
 								);
-		
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+								  
 		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
 				
 		(yy_buffer_stack_max) = num_to_alloc;
@@ -1663,6 +1723,8 @@
 								((yy_buffer_stack),
 								num_to_alloc * sizeof(struct yy_buffer_state*)
 								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
 
 		/* zero only the new slots.*/
 		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -1721,8 +1783,8 @@
 
 /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
  * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
  * 
  * @return the newly allocated buffer state object.
  */
@@ -1961,7 +2023,7 @@
 
 #define YYTABLES_NAME "yytables"
 
-#line 61 "minccalc/lex.l"
+#line 63 "lex.l"
 
 
 
--- a/progs/minccalc/lex.l
+++ b/progs/minccalc/lex.l
@@ -1,7 +1,7 @@
 %{
 #include <string.h>
 #include "node.h"
-#include "y.tab.h"
+#include "gram.h"
 
 int lexpos = 0;
 #define setpos() yylval.pos = lexpos; lexpos += yyleng
@@ -19,6 +19,8 @@
 abs            setpos(); return ABS;
 max            setpos(); return MAX;
 min            setpos(); return MIN;
+imax           setpos(); return IMAX;
+imin           setpos(); return IMIN;
 exp            setpos(); return EXP;
 log            setpos(); return LOG;
 sin            setpos(); return SIN;
--- a/progs/minccalc/minccalc.man1
+++ b/progs/minccalc/minccalc.man1
@@ -228,6 +228,8 @@
    prod - the product of the elements of
    max  - the maximum value of
    min  - the minimum value of
+   imax - the index of the maximum value of
+   imin - the index of the minimum value of
    V[s] - the s'th element of vector V with origin 0.
 
 Symbol names are introduced into a global symbol table by assignment
--- a/progs/minccalc/node.c
+++ b/progs/minccalc/node.c
@@ -17,6 +17,8 @@
         { NODETYPE_LEN,      "len" },
         { NODETYPE_MAX,      "max" },
         { NODETYPE_MIN,      "min" },
+        { NODETYPE_IMAX,     "imax" },
+        { NODETYPE_IMIN,     "imin" },
         { NODETYPE_IDENT,    "ident" },
         { NODETYPE_REAL,     "real" },
         { NODETYPE_LET,      "let" },
--- a/progs/minccalc/node.h
+++ b/progs/minccalc/node.h
@@ -39,6 +39,8 @@
    NODETYPE_LEN, 
    NODETYPE_MAX, 
    NODETYPE_MIN, 
+   NODETYPE_IMAX, 
+   NODETYPE_IMIN, 
    NODETYPE_IDENT, 
    NODETYPE_REAL, 
    NODETYPE_LET,
deleted file mode 100644
--- a/progs/minccalc/y.tab.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* A Bison parser, made from gram.y, by GNU bison 1.75.  */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
-
-   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, 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.  */
-
-/* As a special exception, when this file is copied by Bison into a
-   Bison output file, you may use that output file without restriction.
-   This special exception was added by the Free Software Foundation
-   in version 1.24 of Bison.  */
-
-#ifndef BISON_Y_TAB_H
-# define BISON_Y_TAB_H
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     NAN = 258,
-     IN = 259,
-     TO = 260,
-     IDENT = 261,
-     REAL = 262,
-     AVG = 263,
-     PROD = 264,
-     SUM = 265,
-     LET = 266,
-     NEG = 267,
-     LEN = 268,
-     MAX = 269,
-     MIN = 270,
-     ISNAN = 271,
-     SQRT = 272,
-     ABS = 273,
-     EXP = 274,
-     LOG = 275,
-     SIN = 276,
-     COS = 277,
-     TAN = 278,
-     ASIN = 279,
-     ACOS = 280,
-     ATAN = 281,
-     CLAMP = 282,
-     SEGMENT = 283,
-     LT = 284,
-     LE = 285,
-     GT = 286,
-     GE = 287,
-     EQ = 288,
-     NE = 289,
-     NOT = 290,
-     AND = 291,
-     OR = 292,
-     IF = 293,
-     ELSE = 294,
-     FOR = 295
-   };
-#endif
-#define NAN 258
-#define IN 259
-#define TO 260
-#define IDENT 261
-#define REAL 262
-#define AVG 263
-#define PROD 264
-#define SUM 265
-#define LET 266
-#define NEG 267
-#define LEN 268
-#define MAX 269
-#define MIN 270
-#define ISNAN 271
-#define SQRT 272
-#define ABS 273
-#define EXP 274
-#define LOG 275
-#define SIN 276
-#define COS 277
-#define TAN 278
-#define ASIN 279
-#define ACOS 280
-#define ATAN 281
-#define CLAMP 282
-#define SEGMENT 283
-#define LT 284
-#define LE 285
-#define GT 286
-#define GE 287
-#define EQ 288
-#define NE 289
-#define NOT 290
-#define AND 291
-#define OR 292
-#define IF 293
-#define ELSE 294
-#define FOR 295
-
-
-
-
-#ifndef YYSTYPE
-#line 15 "gram.y"
-typedef union {
-int      pos;
-node_t   node;
-double   real;
-ident_t  ident;
-} yystype;
-/* Line 1281 of /usr/share/bison/yacc.c.  */
-#line 127 "y.tab.h"
-# define YYSTYPE yystype
-#endif
-
-extern YYSTYPE yylval;
-
-
-#endif /* not BISON_Y_TAB_H */
-
--- a/progs/mincpik/mincpik
+++ b/progs/mincpik/mincpik
@@ -432,7 +432,7 @@
    $bw = int($bh/10);
    
    # get range if not defined
-   if(!defined(@{$opt{'image_range'}[0]})){
+   if(!defined($opt{'image_range'}[0])){
       print STDERR "Getting image range\n" if $opt{'verbose'};
       
       @buf = split(/\n/, `mincstats -min -max -quiet $infile`);
--- a/progs/mincstats/mincstats.c
+++ b/progs/mincstats/mincstats.c
@@ -521,7 +521,7 @@
     double sigma_T;
     double mu_T;
     double mu_k;
-    int sum;
+    double sum;
     int k_low, k_high;
     double mu_0, mu_1, mu;
 
@@ -530,12 +530,12 @@
         return (0.0);
     }
 
-    sum = 0;
+    sum = 0.0;
     for (i = 0; i < hist_bins; i++)
-        sum += histo[i];
+        sum += (double)histo[i];
 
     for (i = 0; i < hist_bins; i++)
-        p[i] = histo[i] * 1.0 / sum;
+        p[i] = (double)histo[i] / sum;
 
     mu_T = 0.0;
     for (i = 0; i < hist_bins; i++)