]> Creatis software - clitk.git/commitdiff
Merge branch 'master' of /home/dsarrut/clitk3.server
authorpierre gueth <pierre.gueth@creatis.insa-lyon.fr>
Mon, 24 Oct 2011 12:20:41 +0000 (14:20 +0200)
committerpierre gueth <pierre.gueth@creatis.insa-lyon.fr>
Mon, 24 Oct 2011 12:20:41 +0000 (14:20 +0200)
.gitignore [new file with mode: 0644]
common/CMakeLists.txt
common/clitkGateAsciiImageIO.cxx [new file with mode: 0644]
common/clitkGateAsciiImageIO.h [new file with mode: 0644]
common/clitkGateAsciiImageIOFactory.cxx [new file with mode: 0644]
common/clitkGateAsciiImageIOFactory.h [new file with mode: 0644]
common/clitkIO.cxx
tools/CMakeLists.txt
tools/clitkGammaIndex.cxx

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d5a1572
--- /dev/null
@@ -0,0 +1,2 @@
+*.swp
+build
index 9f92d71426d8901a5dc0dc21cc76aa0a91af7f47..ec826a2340d4437e5d4dd546c865a2609671f74d 100644 (file)
@@ -24,6 +24,8 @@ SET(clitkCommon_SRC
   clitkXdrImageIOFactory.cxx
   clitkHndImageIO.cxx
   clitkHndImageIOFactory.cxx
+  clitkGateAsciiImageIO.cxx
+  clitkGateAsciiImageIOFactory.cxx
   clitkDicomRTDoseIO.cxx
   clitkDicomRTDoseIOFactory.cxx
   clitkOrientation.cxx
diff --git a/common/clitkGateAsciiImageIO.cxx b/common/clitkGateAsciiImageIO.cxx
new file mode 100644 (file)
index 0000000..f3d4a8d
--- /dev/null
@@ -0,0 +1,278 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+// std include
+#include <regex.h>
+#include <cstdio>
+#include <sstream>
+#include <iostream>
+using std::cout;
+using std::endl;
+
+// clitk include
+#include "clitkGateAsciiImageIO.h"
+#include "clitkCommon.h"
+
+// itk include
+#include <itkMetaDataObject.h>
+
+std::ostream& operator<<(std::ostream& os, const clitk::GateAsciiImageIO::GateAsciiHeader& header)
+{
+    os << "matrix_size=[" << header.matrix_size[0] << "," << header.matrix_size[1] << "," << header.matrix_size[2] << "]" << endl;
+    os << "resolution=[" << header.resolution[0] << "," << header.resolution[1] << "," << header.resolution[2] << "]" << endl;
+    os << "voxel_size=[" << header.voxel_size[0] << "," << header.voxel_size[1] << "," << header.voxel_size[2] << "]" << endl;
+    os << "nb_value=" << header.nb_value << endl;
+    return os;
+}
+
+//--------------------------------------------------------------------
+// Read Image Information
+void clitk::GateAsciiImageIO::ReadImageInformation()
+{
+    FILE* handle = fopen(m_FileName.c_str(),"r");
+    if (!handle) {
+       itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
+       return;
+    }
+
+    GateAsciiHeader header;
+    if (!ReadHeader(handle,header)) {
+       itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
+       fclose(handle);
+       return;
+    }
+    fclose(handle);
+
+    int real_length = -1;
+    double real_spacing = 0;
+    for (int kk=0; kk<3; kk++) {
+       if (header.resolution[kk]>1) {
+           if (real_length>0) {
+               itkGenericExceptionMacro(<< "Could not image dimension: " << m_FileName);
+               return;
+           }
+           real_length = header.resolution[kk];
+           real_spacing = header.voxel_size[kk];
+       }
+    }
+    assert(real_length == header.nb_value);
+
+    // Set image information
+    SetNumberOfDimensions(2);
+    SetDimensions(0, real_length);
+    SetDimensions(1, 1);
+    SetSpacing(0, real_spacing);
+    SetSpacing(1, 1);
+    SetOrigin(0, 0);
+    SetOrigin(1, 0);
+    SetComponentType(itk::ImageIOBase::DOUBLE);
+}
+
+//--------------------------------------------------------------------
+bool clitk::GateAsciiImageIO::CanReadFile(const char* FileNameToRead)
+{
+    std::string filename(FileNameToRead);
+
+    { // check extension
+       std::string filenameext = GetExtension(filename);
+       if (filenameext != "txt") return false;
+    }
+
+    { // check header
+       FILE* handle = fopen(filename.c_str(),"r");
+       if (!handle) return false;
+
+       GateAsciiHeader header;
+       if (!ReadHeader(handle,header)) { fclose(handle); return false; }
+       fclose(handle);
+    }
+
+    return true;
+}
+
+//--------------------------------------------------------------------
+// Read Line in file
+bool clitk::GateAsciiImageIO::ReadLine(FILE* handle, std::string& line)
+{
+    std::stringstream stream;
+    while (true)
+    {
+       char item;
+       if (ferror(handle)) return false;
+       if (fread(&item,1,1,handle) != 1) return false;
+
+       if (item=='\n' or feof(handle)) {
+           line = stream.str();
+           return true;
+       }
+
+       stream << item;
+    }
+}
+
+std::string ExtractMatch(const std::string& base, const regmatch_t& match) 
+{
+    return base.substr(match.rm_so,match.rm_eo-match.rm_so);
+}
+
+template <typename T>
+T ConvertFromString(const std::string& value)
+{
+    std::stringstream stream;
+    stream << value;
+    T converted;
+    stream >> converted;
+    return converted;
+}
+
+//--------------------------------------------------------------------
+// Read Image Header
+bool clitk::GateAsciiImageIO::ReadHeader(FILE* handle, GateAsciiHeader& header)
+{
+    assert(handle);
+    std::string line;
+
+    regex_t re_comment;
+    regex_t re_matrix_size;
+    regex_t re_resol;
+    regex_t re_voxel_size;
+    regex_t re_nb_value;
+    regmatch_t matches[4];
+
+    { // build regex
+       int ret = 0;
+       ret = regcomp(&re_comment,"^#.+$",REG_EXTENDED|REG_NEWLINE);
+       assert(ret == 0);
+       ret = regcomp(&re_matrix_size,"^# +Matrix *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",REG_EXTENDED|REG_NEWLINE);
+       assert(ret == 0);
+       ret = regcomp(&re_resol,"^# +Resol *= +\\(([0-9]+),([0-9]+),([0-9]+)\\)$",REG_EXTENDED|REG_NEWLINE);
+       assert(ret == 0);
+       ret = regcomp(&re_voxel_size,"^# +Voxel *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",REG_EXTENDED|REG_NEWLINE);
+       assert(ret == 0);
+       ret = regcomp(&re_nb_value,"^# +nbVal *= +([0-9]+)$",REG_EXTENDED|REG_NEWLINE);
+       assert(ret == 0);
+    }
+
+    if (!ReadLine(handle,line)) return false;
+    if (regexec(&re_comment,line.c_str(),1,matches,0) == REG_NOMATCH) return false;
+
+    if (!ReadLine(handle,line)) return false;
+    if (regexec(&re_matrix_size,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
+    header.matrix_size[0] = ConvertFromString<double>(ExtractMatch(line,matches[1]));
+    header.matrix_size[1] = ConvertFromString<double>(ExtractMatch(line,matches[2]));
+    header.matrix_size[2] = ConvertFromString<double>(ExtractMatch(line,matches[3]));
+
+    if (!ReadLine(handle,line)) return false;
+    if (regexec(&re_resol,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
+    header.resolution[0] = ConvertFromString<int>(ExtractMatch(line,matches[1]));
+    header.resolution[1] = ConvertFromString<int>(ExtractMatch(line,matches[2]));
+    header.resolution[2] = ConvertFromString<int>(ExtractMatch(line,matches[3]));
+
+    if (!ReadLine(handle,line)) return false;
+    if (regexec(&re_voxel_size,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
+    header.voxel_size[0] = ConvertFromString<double>(ExtractMatch(line,matches[1]));
+    header.voxel_size[1] = ConvertFromString<double>(ExtractMatch(line,matches[2]));
+    header.voxel_size[2] = ConvertFromString<double>(ExtractMatch(line,matches[3]));
+
+    if (!ReadLine(handle,line)) return false;
+    if (regexec(&re_nb_value,line.c_str(),2,matches,0) == REG_NOMATCH) return false;
+    header.nb_value = ConvertFromString<int>(ExtractMatch(line,matches[1]));
+
+    if (!ReadLine(handle,line)) return false;
+    if (regexec(&re_comment,line.c_str(),1,matches,0) == REG_NOMATCH) return false;
+
+    return true;
+}
+
+//--------------------------------------------------------------------
+// Read Image Content
+void clitk::GateAsciiImageIO::Read(void* abstract_buffer)
+{
+    FILE* handle = fopen(m_FileName.c_str(),"r");
+    if (!handle) {
+       itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
+       return;
+    }
+
+    GateAsciiHeader header;
+    if (!ReadHeader(handle,header)) {
+       itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
+       fclose(handle);
+       return;
+    }
+
+    {
+       double* buffer = static_cast<double*>(abstract_buffer);
+       int read_count = 0;
+       while (true) { 
+           std::string line;
+           if (!ReadLine(handle,line)) break;
+           *buffer = ConvertFromString<double>(line);
+           read_count++;
+           buffer++;
+       }
+       assert(read_count == header.nb_value);
+    }
+
+    fclose(handle);
+}
+
+//--------------------------------------------------------------------
+bool clitk::GateAsciiImageIO::CanWriteFile(const char* FileNameToWrite)
+{
+    if (GetExtension(std::string(FileNameToWrite)) != "txt") return false;
+    return true;
+}
+
+void clitk::GateAsciiImageIO::WriteImageInformation()
+{
+    cout << GetNumberOfDimensions() << endl;
+}
+
+bool clitk::GateAsciiImageIO::SupportsDimension(unsigned long dim)
+{
+    if (dim==2) return true;
+    return false;
+}
+
+//--------------------------------------------------------------------
+// Write Image
+void clitk::GateAsciiImageIO::Write(const void* abstract_buffer)
+{
+    const unsigned long nb_value = GetDimensions(0)*GetDimensions(1);
+    std::stringstream stream;
+    stream << "######################" << endl;
+    stream << "# Matrix Size= (" << GetSpacing(0)*GetDimensions(0) << "," << GetSpacing(1)*GetDimensions(1) << ",1)" << endl;
+    stream << "# Resol      = (" << GetDimensions(0) << "," << GetDimensions(1) << ",1)" << endl;
+    stream << "# VoxelSize  = (" << GetSpacing(0) << "," << GetSpacing(1) << ",1)" << endl;
+    stream << "# nbVal      = " << nb_value << endl;
+    stream << "######################" << endl;
+
+    const double* buffer = static_cast<const double*>(abstract_buffer);
+    for (unsigned long kk=0; kk<nb_value; kk++) { stream << buffer[kk] << endl; }
+
+    FILE* handle = fopen(m_FileName.c_str(),"w");
+    if (!handle) {
+       itkGenericExceptionMacro(<< "Could not open file (for writing): " << m_FileName);
+       return;
+    }
+
+    fwrite(stream.str().c_str(),1,stream.str().size(),handle);
+
+    fclose(handle);
+}
diff --git a/common/clitkGateAsciiImageIO.h b/common/clitkGateAsciiImageIO.h
new file mode 100644 (file)
index 0000000..d0abbea
--- /dev/null
@@ -0,0 +1,84 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+#ifndef CLITKGATEASCIIIMAGEIO_H
+#define CLITKGATEASCIIIMAGEIO_H
+
+// itk include
+#include "itkImageIOBase.h"
+
+#if defined (_MSC_VER) && (_MSC_VER < 1600)
+//SR: taken from
+//#include "msinttypes/stdint.h"
+typedef unsigned int uint32_t;
+#else
+#include <stdint.h>
+#endif
+
+namespace clitk {
+
+    //====================================================================
+    // Class for reading gate ascii Image file format
+    class GateAsciiImageIO: public itk::ImageIOBase
+    {
+       public: 
+           /** Standard class typedefs. */
+           typedef GateAsciiImageIO        Self;
+           typedef itk::ImageIOBase        Superclass;
+           typedef itk::SmartPointer<Self> Pointer;    
+           typedef signed short int        PixelType;
+
+           struct GateAsciiHeader {
+               double matrix_size[3];
+               int resolution[3];
+               double voxel_size[3];
+               int nb_value;
+           };
+
+           GateAsciiImageIO():Superclass() {;}
+
+           /** Method for creation through the object factory. */
+           itkNewMacro(Self);
+
+           /** Run-time type information (and related methods). */
+           itkTypeMacro(GateAsciiImageIO, ImageIOBase);
+
+           /*-------- This part of the interface deals with reading data. ------ */
+           virtual void ReadImageInformation();
+           virtual bool CanReadFile( const char* FileNameToRead );
+           virtual void Read(void * buffer);
+
+           /*-------- This part of the interfaces deals with writing data. ----- */
+           virtual void WriteImageInformation();
+           virtual bool CanWriteFile(const char* filename);
+           virtual void Write(const void* buffer);
+
+           virtual bool SupportsDimension(unsigned long dim);
+
+       protected:
+
+           static bool ReadHeader(FILE* handle, GateAsciiHeader& header);
+           static bool ReadLine(FILE* handle, std::string& line);
+
+    }; // end class GateAsciiImageIO
+} // end namespace
+
+// explicit template instantiation
+//template class itk::CreateObjectFunction<clitk::GateAsciiImageIO>;
+
+#endif /* end #define CLITKGATEASCIIIMAGEIO_H */
+
diff --git a/common/clitkGateAsciiImageIOFactory.cxx b/common/clitkGateAsciiImageIOFactory.cxx
new file mode 100644 (file)
index 0000000..7c78f7d
--- /dev/null
@@ -0,0 +1,29 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+#include "clitkGateAsciiImageIOFactory.h"
+
+//====================================================================
+clitk::GateAsciiImageIOFactory::GateAsciiImageIOFactory()
+{
+  this->RegisterOverride("itkImageIOBase",
+                         "GateAsciiImageIO",
+                         "GateAscii Image IO",
+                         1,
+                         itk::CreateObjectFunction<GateAsciiImageIO>::New());
+}
diff --git a/common/clitkGateAsciiImageIOFactory.h b/common/clitkGateAsciiImageIOFactory.h
new file mode 100644 (file)
index 0000000..bae5ac3
--- /dev/null
@@ -0,0 +1,74 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+#ifndef CLITKGATEASCIIIMAGEIOFACTORY_H
+#define CLITKGATEASCIIIMAGEIOFACTORY_H
+
+// clitk include
+#include "clitkGateAsciiImageIO.h"
+
+// itk include
+#include "itkImageIOBase.h"
+#include "itkObjectFactoryBase.h"
+#include "itkVersion.h"
+
+namespace clitk {
+
+    //====================================================================
+    // Factory for reading GateAscii Image file format
+    class GateAsciiImageIOFactory: public itk::ObjectFactoryBase
+    {
+       public:
+           /** Standard class typedefs. */
+           typedef GateAsciiImageIOFactory        Self;
+           typedef itk::ObjectFactoryBase         Superclass;
+           typedef itk::SmartPointer<Self>        Pointer;
+           typedef itk::SmartPointer<const Self>  ConstPointer;
+
+           /** Class methods used to interface with the registered factories. */
+           const char* GetITKSourceVersion(void) const {
+               return ITK_SOURCE_VERSION;
+           }
+
+           const char* GetDescription(void) const {
+               return "GateAscii ImageIO Factory, allows the loading of gate ascii images into insight";
+           }
+
+           /** Method for class instantiation. */
+           itkFactorylessNewMacro(Self);
+
+           /** Run-time type information (and related methods). */
+           itkTypeMacro(GateAsciiImageIOFactory, ObjectFactoryBase);
+
+           /** Register one factory of this type  */
+           static void RegisterOneFactory(void) {
+               ObjectFactoryBase::RegisterFactory( Self::New() );
+           }   
+
+       protected:
+           GateAsciiImageIOFactory();
+           ~GateAsciiImageIOFactory() {};
+
+       private:
+           GateAsciiImageIOFactory(const Self&); //purposely not implemented
+           void operator=(const Self&); //purposely not implemented
+    };
+
+} // end namespace
+
+#endif /* end #define CLITKGATEASCIIIMAGEIOFACTORY_H */
+
index d2f775853a9433c7cd77663822ace3915e68aa79..1acd352808ba3ff8f01a8beaa6cd0e2db2ddc66e 100644 (file)
 #include "clitkVfImageIOFactory.h"
 #include "clitkXdrImageIOFactory.h"
 #include "clitkHndImageIOFactory.h"
+#include "clitkGateAsciiImageIOFactory.h"
 
 //--------------------------------------------------------------------
 // Register factories
 void clitk::RegisterClitkFactories()
 {
+  clitk::GateAsciiImageIOFactory::RegisterOneFactory();
   clitk::DicomRTDoseIOFactory::RegisterOneFactory();
 #if ITK_VERSION_MAJOR <= 3
   itk::ImageIOFactory::RegisterBuiltInFactories();
index 1f2b07a377579d4ff54986a46f3069515107f2fb..eb04d25a276cc3222deaa14c213ba7133f0e900e 100644 (file)
@@ -126,7 +126,7 @@ IF (CLITK_BUILD_TOOLS)
 
   WRAP_GGO(clitkGammaIndex_GGO_C clitkGammaIndex.ggo)
   ADD_EXECUTABLE(clitkGammaIndex clitkGammaIndex.cxx ${clitkGammaIndex_GGO_C})
-  TARGET_LINK_LIBRARIES(clitkGammaIndex vtkCommon vtkFiltering vtkGraphics vtkIO vtkImaging)
+  TARGET_LINK_LIBRARIES(clitkGammaIndex clitkCommon ${VTK_LIBRARIES} ${ITK_LIBRARIES} vtkIO)
   SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkGammaIndex)
 
   ADD_EXECUTABLE(clitkImageArithm clitkImageArithm.cxx)
index 08d7aef9da81921110bf56365bd42d0d5137e8b1..be0f8072218330f4b82a99ddc7c1b7f50419698e 100644 (file)
@@ -32,241 +32,275 @@ using std::cout;
 
 #include "clitkGammaIndex_ggo.h"
 
-vtkImageData *loadImage(const std::string &filename) {
-  vtkImageReader2 *reader = vtkMetaImageReader::New();
-  //vtkImageReader2 *reader = vtkPNGReader::New();
-  reader->SetFileName(filename.c_str());
-  reader->Update();
+#include <clitkIO.h>
+#include <vvImage.h>
+#include <vvImageReader.h>
+#include <vvImageWriter.h>
 
-  vtkImageData *image = reader->GetOutput();
-  image->Register(NULL);
-  reader->Delete();
+#include <itkImage.h>
+#include <itkImageRegionIterator.h>
+typedef itk::Image<double> OutputImageType;
+typedef itk::ImageRegionIterator<OutputImageType> OutputImageIterator;
 
-  return image;
+vtkImageData* loadImage(const std::string& filename)
+{
+    vvImageReader::Pointer reader = vvImageReader::New();
+    reader->SetInputFilename(filename);
+    reader->Update();
+    vvImage::Pointer vvimage = reader->GetOutput();
+    if (!vvimage) { cerr << "can't load " << filename << endl; return NULL; }
+
+    vtkImageData *image = vtkImageData::New();
+    image->DeepCopy(vvimage->GetFirstVTKImageData());
+    return image;
 }
 
-void saveImage(vtkImageData *image,const std::string &filename) {
-  cout << "saving " << filename << endl;
-  vtkImageWriter *writer = vtkMetaImageWriter::New();
-  writer->SetFileName(filename.c_str());
-  writer->SetInput(image);
-  writer->Write();
-  writer->Delete();
+void saveImage(OutputImageType* image,const std::string &filename) {
+    vvImage::Pointer vvimage = vvImage::New();
+    vvimage->AddItkImage(image);
+
+    vvImageWriter::Pointer writer = vvImageWriter::New();
+    writer->SetOutputFileName(filename.c_str());
+    writer->SetInput(vvimage);
+    writer->Update();
 }
 
+
 void insertTriangles(vtkCellArray *cells, vtkPoints *points, const vtkIdType ids[4]) {
-  double p0[3]; points->GetPoint(ids[0],p0);
-  double p1[3]; points->GetPoint(ids[1],p1);
-  double p2[3]; points->GetPoint(ids[2],p2);
-  double p3[3]; points->GetPoint(ids[3],p3);
-  //cout << "----------------------------------" << endl;
-  //cout << "p0=[" << p0[0] << "," << p0[1] << "," << p0[2] << "]" << endl;
-  //cout << "p1=[" << p1[0] << "," << p1[1] << "," << p1[2] << "]" << endl;
-  //cout << "p2=[" << p2[0] << "," << p2[1] << "," << p2[2] << "]" << endl;
-  //cout << "p3=[" << p3[0] << "," << p3[1] << "," << p3[2] << "]" << endl;
-
-  double center[] = {0,0,0};
-  for (int kk=0; kk<3; kk++) {
-    center[kk] += p0[kk];
-    center[kk] += p1[kk];
-    center[kk] += p2[kk];
-    center[kk] += p3[kk];
-    center[kk] /= 4.;
-  }
-
-  vtkIdType center_id = points->InsertNextPoint(center);
-  //cout << "center=[" << center[0] << "," << center[1] << "," << center[2] << "]" << endl;
-
-  cells->InsertNextCell(3);
-  cells->InsertCellPoint(ids[0]);
-  cells->InsertCellPoint(ids[1]);
-  cells->InsertCellPoint(center_id);
-
-  cells->InsertNextCell(3);
-  cells->InsertCellPoint(ids[1]);
-  cells->InsertCellPoint(ids[3]);
-  cells->InsertCellPoint(center_id);
-
-  cells->InsertNextCell(3);
-  cells->InsertCellPoint(ids[3]);
-  cells->InsertCellPoint(ids[2]);
-  cells->InsertCellPoint(center_id);
-
-  cells->InsertNextCell(3);
-  cells->InsertCellPoint(ids[2]);
-  cells->InsertCellPoint(ids[0]);
-  cells->InsertCellPoint(center_id);
+    double p0[3]; points->GetPoint(ids[0],p0);
+    double p1[3]; points->GetPoint(ids[1],p1);
+    double p2[3]; points->GetPoint(ids[2],p2);
+    double p3[3]; points->GetPoint(ids[3],p3);
+    //cout << "----------------------------------" << endl;
+    //cout << "p0=[" << p0[0] << "," << p0[1] << "," << p0[2] << "]" << endl;
+    //cout << "p1=[" << p1[0] << "," << p1[1] << "," << p1[2] << "]" << endl;
+    //cout << "p2=[" << p2[0] << "," << p2[1] << "," << p2[2] << "]" << endl;
+    //cout << "p3=[" << p3[0] << "," << p3[1] << "," << p3[2] << "]" << endl;
+
+    double center[] = {0,0,0};
+    for (int kk=0; kk<3; kk++) {
+       center[kk] += p0[kk];
+       center[kk] += p1[kk];
+       center[kk] += p2[kk];
+       center[kk] += p3[kk];
+       center[kk] /= 4.;
+    }
+
+    vtkIdType center_id = points->InsertNextPoint(center);
+    //cout << "center=[" << center[0] << "," << center[1] << "," << center[2] << "]" << endl;
+
+    cells->InsertNextCell(3);
+    cells->InsertCellPoint(ids[0]);
+    cells->InsertCellPoint(ids[1]);
+    cells->InsertCellPoint(center_id);
+
+    cells->InsertNextCell(3);
+    cells->InsertCellPoint(ids[1]);
+    cells->InsertCellPoint(ids[3]);
+    cells->InsertCellPoint(center_id);
+
+    cells->InsertNextCell(3);
+    cells->InsertCellPoint(ids[3]);
+    cells->InsertCellPoint(ids[2]);
+    cells->InsertCellPoint(center_id);
+
+    cells->InsertNextCell(3);
+    cells->InsertCellPoint(ids[2]);
+    cells->InsertCellPoint(ids[0]);
+    cells->InsertCellPoint(center_id);
+}
+
+void insertLine(vtkCellArray *cells, vtkPoints *points, const vtkIdType ids[2]) {
+    cells->InsertNextCell(2);
+    cells->InsertCellPoint(ids[0]);
+    cells->InsertCellPoint(ids[1]);
 }
 
 double getMaximum(vtkImageData *image) {
-  bool first = true;
-  double maximum = 0;
+    bool first = true;
+    double maximum = 0;
 
-  for (int kk=0; kk<image->GetNumberOfPoints(); kk++) {
-    double value = image->GetPointData()->GetScalars()->GetTuple1(kk);
+    vtkPointData* point_data = image->GetPointData();
+    assert(point_data);
+    vtkDataArray* scalars = point_data->GetScalars();
+    assert(scalars);
 
-    if (first) {
-      maximum = value;
-      first = false;
-      continue;
-    }
+    for (int kk=0; kk<image->GetNumberOfPoints(); kk++) {
+       double value = scalars->GetTuple1(kk);
+
+       if (first) {
+           maximum = value;
+           first = false;
+           continue;
+       }
 
-    if (maximum<value) maximum = value;
-  }
+       if (maximum<value) maximum = value;
+    }
 
-  return maximum;
+    return maximum;
 }
 
+
 vtkPolyData *buildPlane(vtkImageData *image,double spatial_margin,double dose_margin) {
-  vtkPoints *points = vtkPoints::New();
-  for (int kk=0; kk<image->GetNumberOfPoints(); kk++) {
-    double *point = image->GetPoint(kk);
-    double value = image->GetPointData()->GetScalars()->GetTuple1(kk);
-    assert(value>=0);
-    assert(point[2]==0);
-    point[2] = value;
-
-    point[0] /= spatial_margin;
-    point[1] /= spatial_margin;
-    point[2] /= dose_margin;
+    vtkPoints *points = vtkPoints::New();
+    for (int kk=0; kk<image->GetNumberOfPoints(); kk++) {
+       double *point = image->GetPoint(kk);
+       double value = image->GetPointData()->GetScalars()->GetTuple1(kk);
+       assert(value>=0);
+       assert(point[2]==0);
+       point[2] = value;
+
+       point[0] /= spatial_margin;
+       point[1] /= spatial_margin;
+       point[2] /= dose_margin;
 
 #ifndef NDEBUG
-    vtkIdType point_id = points->InsertNextPoint(point);
-    assert(kk==point_id);
+       vtkIdType point_id = points->InsertNextPoint(point);
+       assert(kk==point_id);
 #else
-    points->InsertNextPoint(point);
+       points->InsertNextPoint(point);
 #endif
-  }
-
-  vtkCellArray *cells = vtkCellArray::New();
-  for (int kk=0; kk<image->GetNumberOfCells(); kk++) {
-    vtkCell *cell = image->GetCell(kk);
-    assert(cell->GetNumberOfPoints()==4);
-    insertTriangles(cells,points,cell->GetPointIds()->GetPointer(0));
-  }
-
-  vtkPolyData *data = vtkPolyData::New();
-  data->SetPoints(points);
-  data->SetPolys(cells);
-  points->Delete();
-  cells->Delete();
-
-  return data;
-}
+    }
 
-void assert2D(vtkImageData *image) {
-#ifndef NDEBUG
-  int *extent = image->GetWholeExtent();
-  assert(extent[4]==0);
-  assert(extent[5]==0);
-#endif
+    vtkCellArray *cells = vtkCellArray::New();
+    for (int kk=0; kk<image->GetNumberOfCells(); kk++) {
+       vtkCell *cell = image->GetCell(kk);
+
+       if (cell->GetNumberOfPoints()==4) {
+           insertTriangles(cells,points,cell->GetPointIds()->GetPointer(0));
+           continue;
+       }
+
+       if (cell->GetNumberOfPoints()==2) {
+           insertLine(cells,points,cell->GetPointIds()->GetPointer(0));
+           continue;
+       }
+
+       assert(false);
+    }
+
+    vtkPolyData *data = vtkPolyData::New();
+    data->SetPoints(points);
+    data->SetPolys(cells);
+    points->Delete();
+    cells->Delete();
+
+    return data;
 }
 
 int main(int argc,char * argv[])
 {
-  args_info_clitkGammaIndex args_info;
-
-  if (cmdline_parser_clitkGammaIndex(argc, argv, &args_info) != 0)
-    exit(1);
-
-  if (!args_info.absolute_dose_margin_given && !args_info.relative_dose_margin_given) {
-    std::cerr << "Specify either relative or absolute dose margin" << endl;
-    exit(1);
-  }
-
-  bool verbose = args_info.verbose_flag;
-
-  std::string reference_filename(args_info.reference_arg);
-  std::string target_filename(args_info.target_arg);
-  std::string gamma_filename(args_info.output_arg);
-  double space_margin = args_info.spatial_margin_arg;
-  double dose_rel_margin = args_info.relative_dose_margin_arg;
-  double dose_margin = args_info.absolute_dose_margin_arg;
-  bool use_dose_margin = args_info.absolute_dose_margin_given;
-
-  if (verbose) {
-    cout << "reference_filename=" << reference_filename << endl;
-    cout << "target_filename=" << target_filename << endl;
-    cout << "gamma_filename=" << gamma_filename << endl;
-    cout << "space_margin=" << space_margin << endl;
-    if (use_dose_margin) cout << "dose_margin=" << dose_margin << endl;
-    else cout << "dose_rel_margin=" << dose_rel_margin << endl;
-  }
-
-  // load reference
-  vtkImageData *reference = loadImage(reference_filename);
-  assert2D(reference);
-
-  // intensity normalisation
-  if (!use_dose_margin) {
-    dose_margin = getMaximum(reference)*dose_rel_margin;
-    if (verbose) cout << "dose_margin=" << dose_margin << endl;
-  }
-
-  // build surface
-  vtkPolyData *data = buildPlane(reference,space_margin,dose_margin);
-  reference->Delete();
-
-  vtkAbstractCellLocator *locator = vtkCellLocator::New();
-  locator->SetDataSet(data);
-  data->Delete();
-  locator->CacheCellBoundsOn();
-  locator->AutomaticOn();
-  locator->BuildLocator();
-
-  // load target
-  vtkImageData *target = loadImage(target_filename);
-  assert2D(target);
-
-  // allocate output
-  vtkImageData *output = vtkImageData::New();
-  output->SetExtent(target->GetWholeExtent());
-  output->SetOrigin(target->GetOrigin());
-  output->SetSpacing(target->GetSpacing());
-  output->SetScalarTypeToFloat();
-  output->AllocateScalars();
-
-  // fill output
-  unsigned long total = 0;
-  unsigned long over_one = 0;
-  for (int kk=0; kk<target->GetNumberOfPoints(); kk++) {
-    double *point = target->GetPoint(kk);
-    double value = target->GetPointData()->GetScalars()->GetTuple1(kk);
-    assert(value>=0);
-    assert(point[2]==0);
-    point[2] = value;
-
-    point[0] /= space_margin;
-    point[1] /= space_margin;
-    point[2] /= dose_margin;
-
-    double closest_point[3] = {0,0,0};
-    vtkIdType cell_id = 0;
-    int foo = 0;
-    double squared_distance = 0;
-
-    locator->FindClosestPoint(point,closest_point,cell_id,foo,squared_distance);
-
-    double distance = sqrt(squared_distance);
-    output->GetPointData()->GetScalars()->SetTuple1(kk,distance);
-
-    if (value>1) over_one++;
-    total++;
-
-  }
-
-  if (verbose) {
-    cout << "total=" << total << endl;
-    cout << "over_one=" << over_one << endl;
-    cout << "ratio=" << static_cast<float>(over_one)/total << endl;
-  }
-
-  locator->Delete();
-  target->Delete();
-
-  saveImage(output,gamma_filename);
-  output->Delete();
-
-  return 0;
+    clitk::RegisterClitkFactories();
+
+    args_info_clitkGammaIndex args_info;
+
+    if (cmdline_parser_clitkGammaIndex(argc, argv, &args_info) != 0)
+       exit(1);
+
+    if (!args_info.absolute_dose_margin_given && !args_info.relative_dose_margin_given) {
+       std::cerr << "Specify either relative or absolute dose margin" << endl;
+       exit(1);
+    }
+
+    bool verbose = args_info.verbose_flag;
+
+    std::string reference_filename(args_info.reference_arg);
+    std::string target_filename(args_info.target_arg);
+    std::string gamma_filename(args_info.output_arg);
+    double space_margin = args_info.spatial_margin_arg;
+    double dose_rel_margin = args_info.relative_dose_margin_arg;
+    double dose_margin = args_info.absolute_dose_margin_arg;
+    bool use_dose_margin = args_info.absolute_dose_margin_given;
+
+    if (verbose) {
+       cout << "reference_filename=" << reference_filename << endl;
+       cout << "target_filename=" << target_filename << endl;
+       cout << "gamma_filename=" << gamma_filename << endl;
+       cout << "space_margin=" << space_margin << endl;
+       if (use_dose_margin) cout << "dose_margin=" << dose_margin << endl;
+       else cout << "dose_rel_margin=" << dose_rel_margin << endl;
+    }
+
+    // load reference
+    vtkImageData* reference = loadImage(reference_filename);
+    assert(reference);
+
+    // intensity normalisation
+    if (!use_dose_margin) {
+       dose_margin = getMaximum(reference)*dose_rel_margin;
+       if (verbose) cout << "dose_margin=" << dose_margin << endl;
+    }
+
+    // build surface
+    vtkPolyData *data = buildPlane(reference,space_margin,dose_margin);
+    reference->Delete();
+
+    vtkAbstractCellLocator *locator = vtkCellLocator::New();
+    locator->SetDataSet(data);
+    data->Delete();
+    locator->CacheCellBoundsOn();
+    locator->AutomaticOn();
+    locator->BuildLocator();
+
+    // load target
+    vtkImageData* target = loadImage(target_filename);
+    assert(target);
+
+    // allocate output
+    OutputImageType::Pointer output = OutputImageType::New();
+    {
+       OutputImageType::SizeType::SizeValueType output_array_size[2];
+       output_array_size[0] = target->GetDimensions()[0];
+       output_array_size[1] = target->GetDimensions()[1];
+       OutputImageType::SizeType output_size;
+       output_size.SetSize(output_array_size);
+       output->SetRegions(OutputImageType::RegionType(output_size));
+       output->SetOrigin(target->GetOrigin());
+       output->SetSpacing(target->GetSpacing());
+       output->Allocate();
+    }
+
+    // fill output
+    unsigned long  kk = 0;
+    unsigned long over_one = 0;
+    OutputImageIterator iter(output,output->GetLargestPossibleRegion());
+    iter.GoToBegin();
+    while (!iter.IsAtEnd()) {
+       double *point = target->GetPoint(kk);
+       double value = target->GetPointData()->GetScalars()->GetTuple1(kk);
+       assert(value>=0);
+       assert(point[2]==0);
+       point[2] = value;
+
+       point[0] /= space_margin;
+       point[1] /= space_margin;
+       point[2] /= dose_margin;
+
+       double closest_point[3] = {0,0,0};
+       vtkIdType cell_id = 0;
+       int foo = 0;
+       double squared_distance = 0;
+
+       locator->FindClosestPoint(point,closest_point,cell_id,foo,squared_distance);
+       double distance = sqrt(squared_distance);
+       iter.Set(distance);
+
+       if (distance>1) over_one++;
+       kk++;
+       ++iter;
+    }
+
+    if (verbose) {
+       cout << "total=" << kk << endl;
+       cout << "over_one=" << over_one << endl;
+       cout << "ratio=" << static_cast<float>(over_one)/kk << endl;
+    }
+
+    locator->Delete();
+    target->Delete();
+
+    saveImage(output,gamma_filename);
+
+    return 0;
 }