diff --git a/.gitignore b/.gitignore index 715fb71b9..9cacf0724 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ CMakeFiles/ CTestTestfile.cmake .idea/ .githooks/clangFormatMac +/cmake-build-debug/ +/build/ diff --git a/Common/itkTransformixInputPointFileReader.h b/Common/itkTransformixInputPointFileReader.h index e5777a1ff..2deb01554 100644 --- a/Common/itkTransformixInputPointFileReader.h +++ b/Common/itkTransformixInputPointFileReader.h @@ -83,6 +83,11 @@ class ITK_TEMPLATE_EXPORT TransformixInputPointFileReader : public MeshFileReade */ itkGetConstMacro(NumberOfPoints, unsigned long); + /** Get and set whether to read the points from a binary file. + */ + itkGetConstMacro(Binary, bool); + itkSetMacro(Binary, bool); + /** Prepare the allocation of the output mesh during the first back * propagation of the pipeline. Updates the PointsAreIndices and NumberOfPoints. */ @@ -100,6 +105,7 @@ class ITK_TEMPLATE_EXPORT TransformixInputPointFileReader : public MeshFileReade private: unsigned long m_NumberOfPoints{ 0 }; bool m_PointsAreIndices{ false }; + bool m_Binary{ false }; std::ifstream m_Reader{}; }; diff --git a/Common/itkTransformixInputPointFileReader.hxx b/Common/itkTransformixInputPointFileReader.hxx index 67e15425c..1d3343ad6 100644 --- a/Common/itkTransformixInputPointFileReader.hxx +++ b/Common/itkTransformixInputPointFileReader.hxx @@ -40,30 +40,60 @@ TransformixInputPointFileReader::GenerateOutputInformation() { this->m_Reader.close(); } - this->m_Reader.open(this->m_FileName); - /** Read the first entry */ - std::string indexOrPoint; - this->m_Reader >> indexOrPoint; + if( this->m_Binary ) { + this->m_Reader.open(this->m_FileName, std::ios::binary); + + /** Read index flag */ + unsigned long isindex; + this->m_Reader.read((char*) &isindex, sizeof(isindex)); + + if( isindex == 0 ) + { + /** Input points are specified in world coordinates. */ + this->m_PointsAreIndices = false; + } + else //if( indexOrPoint == 1 ) + { + /** Input points are specified as image indices. */ + this->m_PointsAreIndices = true; + } + + /** Read number of points */ + unsigned long nrofpoints; + this->m_Reader.read((char*) &nrofpoints, sizeof(nrofpoints)); + this->m_NumberOfPoints = nrofpoints; + + /** Leave the file open for the generate data method */ - /** Set the IsIndex bool and the number of points.*/ - if (indexOrPoint == "point") - { - /** Input points are specified in world coordinates. */ - this->m_PointsAreIndices = false; - this->m_Reader >> this->m_NumberOfPoints; - } - else if (indexOrPoint == "index") - { - /** Input points are specified as image indices. */ - this->m_PointsAreIndices = true; - this->m_Reader >> this->m_NumberOfPoints; } - else + else //if( this->m_Binary ) { - /** Input points are assumed to be specified as image indices. */ - this->m_PointsAreIndices = true; - this->m_NumberOfPoints = atoi(indexOrPoint.c_str()); + this->m_Reader.open(this->m_FileName); + + /** Read the first entry */ + std::string indexOrPoint; + this->m_Reader >> indexOrPoint; + + /** Set the IsIndex bool and the number of points.*/ + if (indexOrPoint == "point") + { + /** Input points are specified in world coordinates. */ + this->m_PointsAreIndices = false; + this->m_Reader >> this->m_NumberOfPoints; + } + else if (indexOrPoint == "index") + { + /** Input points are specified as image indices. */ + this->m_PointsAreIndices = true; + this->m_Reader >> this->m_NumberOfPoints; + } + else + { + /** Input points are assumed to be specified as image indices. */ + this->m_PointsAreIndices = true; + this->m_NumberOfPoints = atoi(indexOrPoint.c_str()); + } } /** Leave the file open for the generate data method */ @@ -90,6 +120,27 @@ TransformixInputPointFileReader::GenerateData() /** Read the file */ if (this->m_Reader.is_open()) { + if( this->m_Binary ){ + for( unsigned long i = 0; i < this->m_NumberOfPoints; ++i ) + { + // read point from binary file + PointType point; + + if( !this->m_Reader.eof() ) + { + this->m_Reader.read((char*) &point, sizeof(point)); + } else { + std::ostringstream msg; + msg << "The file is not large enough. " + << std::endl << "Filename: " << this->m_FileName + << std::endl; + MeshFileReaderException e( __FILE__, __LINE__, msg.str().c_str(), ITK_LOCATION ); + throw e; + } + points->push_back( point ); + } + } + else //if( this->m_Binary ){ for (unsigned int i = 0; i < this->m_NumberOfPoints; ++i) { // read point from textfile diff --git a/Core/ComponentBaseClasses/elxTransformBase.h b/Core/ComponentBaseClasses/elxTransformBase.h index 9e4ada193..7f8a1d469 100644 --- a/Core/ComponentBaseClasses/elxTransformBase.h +++ b/Core/ComponentBaseClasses/elxTransformBase.h @@ -399,7 +399,7 @@ class ITK_TEMPLATE_EXPORT TransformBase : public BaseComponentSE /** Function to transform coordinates from fixed to moving image. */ void - TransformPointsSomePoints(const std::string & filename) const; + TransformPointsSomePoints(const std::string & filename, const bool binary = false) const; /** Function to transform coordinates from fixed to moving image, given as VTK file. */ void diff --git a/Core/ComponentBaseClasses/elxTransformBase.hxx b/Core/ComponentBaseClasses/elxTransformBase.hxx index 635a78cc7..d43d562fc 100644 --- a/Core/ComponentBaseClasses/elxTransformBase.hxx +++ b/Core/ComponentBaseClasses/elxTransformBase.hxx @@ -686,6 +686,11 @@ TransformBase::TransformPoints() const log::info(" The transform is evaluated on some points, specified in a VTK input point file."); this->TransformPointsSomePointsVTK(def); } + else if (itksys::SystemTools::StringEndsWith(def, ".bin") || itksys::SystemTools::StringEndsWith(def, ".BIN")) + { + log::info(" The transform is evaluated on some points, specified in a binary input point file."); + this->TransformPointsSomePoints(def, true); + } else { log::info(" The transform is evaluated on some points, specified in the input point file."); @@ -721,7 +726,7 @@ TransformBase::TransformPoints() const template void -TransformBase::TransformPointsSomePoints(const std::string & filename) const +TransformBase::TransformPointsSomePoints(const std::string & filename, const bool binary) const { /** Typedef's. */ using FixedImageRegionType = typename FixedImageType::RegionType; @@ -739,6 +744,7 @@ TransformBase::TransformPointsSomePoints(const std::string & filename) /** Construct an ipp-file reader. */ const auto ippReader = itk::TransformixInputPointFileReader::New(); ippReader->SetFileName(filename); + ippReader->SetBinary(binary); /** Read the input points. */ log::info(std::ostringstream{} << " Reading input point file: " << filename); @@ -760,7 +766,7 @@ TransformBase::TransformPointsSomePoints(const std::string & filename) { log::info(" Input points are specified in world coordinates."); } - const unsigned int nrofpoints = ippReader->GetNumberOfPoints(); + const unsigned long nrofpoints = ippReader->GetNumberOfPoints(); log::info(std::ostringstream{} << " Number of specified input points: " << nrofpoints); /** Get the set of input points. */ @@ -794,7 +800,7 @@ TransformBase::TransformPointsSomePoints(const std::string & filename) /** Read the input points, as index or as point. */ if (ippReader->GetPointsAreIndices()) { - for (unsigned int j = 0; j < nrofpoints; ++j) + for (unsigned long j = 0; j < nrofpoints; ++j) { /** The read point from the inutPointSet is actually an index * Cast to the proper type. @@ -811,7 +817,7 @@ TransformBase::TransformPointsSomePoints(const std::string & filename) } else { - for (unsigned int j = 0; j < nrofpoints; ++j) + for (unsigned long j = 0; j < nrofpoints; ++j) { /** Compute index of nearest voxel in fixed image. */ InputPointType point{}; @@ -827,7 +833,7 @@ TransformBase::TransformPointsSomePoints(const std::string & filename) /** Apply the transform. */ log::info(" The input points are transformed."); - for (unsigned int j = 0; j < nrofpoints; ++j) + for (unsigned long j = 0; j < nrofpoints; ++j) { /** Call TransformPoint. */ outputpointvec[j] = this->GetAsITKBaseType()->TransformPoint(inputpointvec[j]); @@ -860,50 +866,85 @@ TransformBase::TransformPointsSomePoints(const std::string & filename) !outputDirectoryPath.empty()) { /** Create filename and file stream. */ - const std::string outputPointsFileName = outputDirectoryPath + "outputpoints.txt"; - std::ofstream outputPointsFile(outputPointsFileName); + const std::string extension = binary ? "bin" : "txt"; + const std::string outputPointsFileName = outputDirectoryPath + "outputpoints." + extension; + + std::ofstream outputPointsFile(outputPointsFileName, binary ? std::ios_base::binary : std::ios_base::out ); outputPointsFile << std::showpoint << std::fixed; log::info(std::ostringstream{} << " The transformed points are saved in: " << outputPointsFileName); - const auto writeToFile = [&outputPointsFile](const auto & rangeOfElements) { - for (const auto element : rangeOfElements) - { - outputPointsFile << element << ' '; - } - }; - - /** Print the results. */ - for (unsigned int j = 0; j < nrofpoints; ++j) - { - /** The input index. */ - outputPointsFile << "Point\t" << j << "\t; InputIndex = [ "; - writeToFile(inputindexvec[j]); - - /** The input point. */ - outputPointsFile << "]\t; InputPoint = [ "; - writeToFile(inputpointvec[j]); - - /** The output index in fixed image. */ - outputPointsFile << "]\t; OutputIndexFixed = [ "; - writeToFile(outputindexfixedvec[j]); + /** Write the results. */ - /** The output point. */ - outputPointsFile << "]\t; OutputPoint = [ "; - writeToFile(outputpointvec[j]); + if (binary) { //Note: for speed, write the transformed points only + unsigned long isindex = ippReader->GetPointsAreIndices() ? 1 : 0; + outputPointsFile.write((char*) &isindex, sizeof(isindex)); - /** The output point minus the input point. */ - outputPointsFile << "]\t; Deformation = [ "; - writeToFile(deformationvec[j]); + unsigned long numberOfPoints = nrofpoints; + outputPointsFile.write((char*) &numberOfPoints, sizeof(numberOfPoints)); - if (alsoMovingIndices) + for( unsigned int j = 0; j < nrofpoints; j++ ) { - /** The output index in moving image. */ - outputPointsFile << "]\t; OutputIndexMoving = [ "; - writeToFile(outputindexmovingvec[j]); - } - - outputPointsFile << "]" << std::endl; - } // end for nrofpoints + if ( ippReader->GetPointsAreIndices() ) + { + /** The output index in fixed image. */ + for( unsigned int i = 0; i < FixedImageDimension; i++ ) + { + outputPointsFile.write((char*) &outputindexfixedvec[ j ][ i ], sizeof(outputindexfixedvec[ j ][ i ]) ); + } + } + else + { + /** The output point. */ + for( unsigned int i = 0; i < FixedImageDimension; i++ ) + { + outputPointsFile.write((char*) &outputpointvec[ j ][ i ], sizeof(outputpointvec[ j ][ i ]) ); + } + } + } // end for nrofpoints + + outputPointsFile.close(); + } + else //if (binary) + { + const auto writeToFile = [&outputPointsFile](const auto & rangeOfElements) { + for (const auto element : rangeOfElements) + { + outputPointsFile << element << ' '; + } + }; + + for (unsigned int j = 0; j < nrofpoints; ++j) + { + /** The input index. */ + outputPointsFile << "Point\t" << j << "\t; InputIndex = [ "; + writeToFile(inputindexvec[j]); + + /** The input point. */ + outputPointsFile << "]\t; InputPoint = [ "; + writeToFile(inputpointvec[j]); + + /** The output index in fixed image. */ + outputPointsFile << "]\t; OutputIndexFixed = [ "; + writeToFile(outputindexfixedvec[j]); + + /** The output point. */ + outputPointsFile << "]\t; OutputPoint = [ "; + writeToFile(outputpointvec[j]); + + /** The output point minus the input point. */ + outputPointsFile << "]\t; Deformation = [ "; + writeToFile(deformationvec[j]); + + if (alsoMovingIndices) + { + /** The output index in moving image. */ + outputPointsFile << "]\t; OutputIndexMoving = [ "; + writeToFile(outputindexmovingvec[j]); + } + + outputPointsFile << "]" << std::endl; + } // end for nrofpoints + } } } // end TransformPointsSomePoints()