diff --git a/Applications/Mapper/include/mapRHelper.h b/Applications/Mapper/include/mapRHelper.h index 8fdfa91..d26e796 100644 --- a/Applications/Mapper/include/mapRHelper.h +++ b/Applications/Mapper/include/mapRHelper.h @@ -1,544 +1,544 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // 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. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL$ */ #ifndef __MAP_R_HELPER_H #define __MAP_R_HELPER_H #include "itkImageFileWriter.h" #include "itkStdStreamLogOutput.h" #include "itkImageSeriesWriter.h" #include "itkNumericSeriesFileNames.h" #include "itkGDCMImageIO.h" #include "itkVersion.h" #include #include #include #include #include #include "gdcmUIDGenerator.h" #include "mapConvert.h" #include "mapExceptionObjectMacros.h" #include "mapImageMappingTask.h" #include "mapGenericImageReader.h" #include "mapRegistrationFileReader.h" #include "mapPointSetMappingTask.h" #include "mapSimpleLandMarkFileWriter.h" #include "mapContinuousElements.h" #include "mapRApplicationData.h" namespace map { namespace apps { namespace mapR { template class TProcessingPolicy> void handleGenericImage(const ApplicationData& appData) { switch (appData._loadedComponentType) { - case ::itk::ImageIOBase::UCHAR: + case ::itk::IOComponentEnum::UCHAR: { TProcessingPolicy::processData(appData); break; } - case ::itk::ImageIOBase::CHAR: + case ::itk::IOComponentEnum::CHAR: { TProcessingPolicy::processData(appData); break; } - case ::itk::ImageIOBase::USHORT: + case ::itk::IOComponentEnum::USHORT: { TProcessingPolicy::processData(appData); break; } - case ::itk::ImageIOBase::SHORT: + case ::itk::IOComponentEnum::SHORT: { TProcessingPolicy::processData(appData); break; } - case ::itk::ImageIOBase::UINT: + case ::itk::IOComponentEnum::UINT: { TProcessingPolicy::processData(appData); break; } - case ::itk::ImageIOBase::INT: + case ::itk::IOComponentEnum::INT: { TProcessingPolicy::processData(appData); break; } - case ::itk::ImageIOBase::ULONG: + case ::itk::IOComponentEnum::ULONG: { TProcessingPolicy::processData(appData); break; } - case ::itk::ImageIOBase::LONG: + case ::itk::IOComponentEnum::LONG: { TProcessingPolicy::processData(appData); break; } - case ::itk::ImageIOBase::FLOAT: + case ::itk::IOComponentEnum::FLOAT: { TProcessingPolicy::processData(appData); break; } - case ::itk::ImageIOBase::DOUBLE: + case ::itk::IOComponentEnum::DOUBLE: { TProcessingPolicy::processData(appData); break; } default: { mapDefaultExceptionStaticMacro(<< "The file uses a pixel component type that is not supported in this application."); } } } /** Helper class that contains the logic that handles the data loading according to the settings in appData. * the loaded data will be stored in app data. */ class LoadingLogic { public: LoadingLogic(ApplicationData& appData); void loadRegistration(); void loadInput(); void loadReferenceImage(); protected: ApplicationData& _appData; }; template class ProcessingLogic { public: typedef ::itk::Image ImageType; using PointSetType = typename ::map::core::continuous::Elements::InternalPointSetType; /** Generates meta data dictionaries with the correct meta data (correlated with needed DICOM tags) to ensure * the correct dicom file generation for each slice of the passed image. * @pre pImage must point to a valid instance.*/ static std::vector generateSliceDictionaries(ImageType* pImage, const map::core::String& uidPrefix, const ApplicationData& appData) { if (!pImage) { mapDefaultExceptionStaticMacro(<< "Cannot generate slice dictionaries. Passed image pointer is invalid (NULL)."); } // Copy the dictionary from the image itk::MetaDataDictionary mappedDict; mappedDict = pImage->GetMetaDataDictionary(); if (appData._loadedMetaDataDictArray.size()) { mappedDict = appData._loadedMetaDataDictArray[0]; } std::vector outputArray; //////////////////////////////////////////// //Step 1: set everything that is valid for all slices // To keep the new series in the same study as the original we need // to keep the same study UID. But we need new series and frame of // reference UID's. gdcm::UIDGenerator suid; std::string seriesUID = suid.Generate(); gdcm::UIDGenerator fuid; std::string frameOfReferenceUID = fuid.Generate(); if (appData._loadedRefMetaDataDictArray.size()) { //result has the same frame of reference UID then template image itk::ExposeMetaData(appData._loadedRefMetaDataDictArray[0], "0020|0052", frameOfReferenceUID); } // Set the UID's for the study, series and frame of reference itk::EncapsulateMetaData(mappedDict, "0020|000e", seriesUID); itk::EncapsulateMetaData(mappedDict, "0020|0052", frameOfReferenceUID); map::core::OStringStream stream; // Series Description - Append new description to current series // description std::string oldSeriesDesc; itk::ExposeMetaData(mappedDict, "0008|103e", oldSeriesDesc); stream.str(""); stream << "regd_" << oldSeriesDesc; // This is an long string and there is a 64 character limit in the // standard unsigned lengthDesc = stream.str().length(); std::string seriesDesc(stream.str(), 0, lengthDesc > 64 ? 64 : lengthDesc); itk::EncapsulateMetaData(mappedDict, "0008|103e", seriesDesc); // Derivation Description - How this image was derived stream.str(""); stream << "mapped by using \"" << map::core::FileDispatch::getFullName( appData._regFileName) << "\" registration file; software: mapR; MatchPoint version: " << MAP_SOURCE_VERSION << ", itk version:" << ITK_SOURCE_VERSION; lengthDesc = stream.str().length(); std::string derivationDesc(stream.str(), 0, lengthDesc > 1024 ? 1024 : lengthDesc); itk::EncapsulateMetaData(mappedDict, "0008|2111", derivationDesc); // Slice Thickness: For now, we store the z spacing stream.str(""); stream << pImage->GetSpacing()[2]; itk::EncapsulateMetaData(mappedDict, "0018|0050", stream.str()); // Spacing Between Slices itk::EncapsulateMetaData(mappedDict, "0018|0088", stream.str()); /////////////////////////////////////////////// //Step 2: Generate a dictionary per slice and // adapt slice specific values itk::ImageRegion<3>::SizeValueType sliceCount = pImage->GetLargestPossibleRegion().GetSize(2); for (itk::ImageRegion<3>::SizeValueType currentSliceIndex = 0; currentSliceIndex < sliceCount; ++currentSliceIndex) { // Create a new dictionary for this slice itk::MetaDataDictionary* pDict = new itk::MetaDataDictionary; // Copy the dictionary from the first slice *pDict = mappedDict; // Set the UID's for the SOP gdcm::UIDGenerator sopuid; std::string sopInstanceUID = sopuid.Generate(); itk::EncapsulateMetaData(*pDict, "0008|0018", sopInstanceUID); itk::EncapsulateMetaData(*pDict, "0002|0003", sopInstanceUID); // Change fields that are slice specific map::core::OStringStream value; value.str(""); value << currentSliceIndex + 1; // Image Number itk::EncapsulateMetaData(*pDict, "0020|0013", value.str()); // Image Position Patient: This is calculated by computing the // physical coordinate of the first pixel in each slice. typename ImageType::PointType position; typename ImageType::IndexType index; index[0] = 0; index[1] = 0; index[2] = currentSliceIndex; pImage->TransformIndexToPhysicalPoint(index, position); value.str(""); value << position[0] << "\\" << position[1] << "\\" << position[2]; itk::EncapsulateMetaData(*pDict, "0020|0032", value.str()); // Slice Location: For now, we store the z component of the Image // Position Patient. value.str(""); value << position[2]; itk::EncapsulateMetaData(*pDict, "0020|1041", value.str()); // Save the dictionary outputArray.push_back(pDict); } return outputArray; } /**write the image data according to the settings in appData. * @pre pImage must point to a valid instance. * @TODO should this method be reworked * right now the tags of dicom image will only be transfered if they are 3D and the series read style is set to DICOM or GDCM. * Thus 2D DICOM images are missed as well as 3D DICOM images that are stored as one image file (default series style).*/ static void doWriting(ImageType* pImage, const ApplicationData& appData) { if (!pImage) { mapDefaultExceptionStaticMacro(<< "Cannot write data. Passed image pointer is invalid (NULL)."); } std::cout << std::endl << "save output file ... "; if (appData._loadedDimensions > 2 && (appData._seriesWriteStyle == map::io::ImageSeriesReadStyle::Dicom || appData._seriesWriteStyle == map::io::ImageSeriesReadStyle::Numeric || appData._seriesWriteStyle == map::io::ImageSeriesReadStyle::GDCM)) { typedef ::itk::Image < TPixelType, IDim - 1 > OutputImageType; using OutputNamesGeneratorType = ::itk::NumericSeriesFileNames; typedef ::itk::ImageSeriesWriter< ImageType, OutputImageType > SeriesWriterType; using ImageIOType = ::itk::GDCMImageIO; ImageIOType::Pointer spGDCMIO = ImageIOType::New(); OutputNamesGeneratorType::Pointer outputNames = OutputNamesGeneratorType::New(); outputNames->SetStartIndex(1); outputNames->SetEndIndex(pImage->GetLargestPossibleRegion().GetSize(pImage->GetImageDimension() - 1)); // Generate the file names map::core::String tempLen = map::core::convert::toStr(static_cast(outputNames->GetEndIndex())); map::core::String seriesFormat = map::core::FileDispatch::createFullPath( map::core::FileDispatch::getPath(appData._outputFileName), map::core::FileDispatch::getName(appData._outputFileName) + ".%0" + map::core::convert::toStrGeneric(tempLen.length()) + "d" + map::core::FileDispatch::getExtension( appData._outputFileName)); std::cout << "(" << seriesFormat << ")... "; outputNames->SetSeriesFormat(seriesFormat.c_str()); // do the output typename SeriesWriterType::Pointer spSeriesWriter = SeriesWriterType::New(); spSeriesWriter->SetInput(pImage); spSeriesWriter->SetFileNames(outputNames->GetFileNames()); std::vector outputArray = generateSliceDictionaries(pImage, spGDCMIO->GetUIDPrefix(), appData); if ((appData._seriesWriteStyle == map::io::ImageSeriesReadStyle::Dicom) || (appData._seriesWriteStyle == map::io::ImageSeriesReadStyle::GDCM)) { spGDCMIO->KeepOriginalUIDOn(); spSeriesWriter->SetImageIO(spGDCMIO); spSeriesWriter->SetMetaDataDictionaryArray(&outputArray); } spSeriesWriter->Update(); for (std::vector::iterator pos = outputArray.begin(); pos != outputArray.end(); ++pos) { delete *pos; } } else { std::cout << "(" << appData._outputFileName << ")... "; using ImageWriterType = ::itk::ImageFileWriter; typename ImageWriterType::Pointer spImageWriter = ImageWriterType::New(); spImageWriter->SetInput(pImage); spImageWriter->SetFileName(appData._outputFileName.c_str()); spImageWriter->SetUseCompression(true); spImageWriter->Update(); } std::cout << "done." << std::endl; }; static typename ::itk::InterpolateImageFunction< ImageType >::Pointer generateInterpolator( ImageMappingInterpolator::Type interpolatorType) { using BaseInterpolatorType = ::itk::InterpolateImageFunction< ImageType >; typename BaseInterpolatorType::Pointer result; switch (interpolatorType) { case ImageMappingInterpolator::NearestNeighbor: { result = ::itk::NearestNeighborInterpolateImageFunction::New(); break; } case ImageMappingInterpolator::BSpline_3: { typename ::itk::BSplineInterpolateImageFunction::Pointer spInterpolator = ::itk::BSplineInterpolateImageFunction::New(); spInterpolator->SetSplineOrder(3); result = spInterpolator; break; } case ImageMappingInterpolator::WSinc_Hamming: { result = ::itk::WindowedSincInterpolateImageFunction::New(); break; } case ImageMappingInterpolator::WSinc_Welch: { result = ::itk::WindowedSincInterpolateImageFunction >::New(); break; } default: { result = ::itk::LinearInterpolateImageFunction::New(); break; } } return result; }; static typename ImageType::Pointer doMapping(const ApplicationData& appData) { using TemplateImageType = ::itk::ImageBase; typedef map::core::Registration RegistrationType; typedef map::core::ImageMappingTask MapperType; typename MapperType::Pointer spMapper = MapperType::New(); auto* pCastedInput = dynamic_cast(appData._input.GetPointer()); typename ImageType::Pointer spResult; auto* pCastedReg = dynamic_cast(appData._spReg.GetPointer()); typename MapperType::ResultImageDescriptorType::Pointer spResultDesc = nullptr; if (appData._spRefImage.IsNotNull()) { auto* pCastedTemplate = dynamic_cast (appData._spRefImage.GetPointer()); spResultDesc = map::core::createFieldRepresentation(*pCastedTemplate); } try { std::cout << std::endl << "map input file... "; spMapper->setInputImage(pCastedInput); spMapper->setRegistration(pCastedReg); spMapper->setResultImageDescriptor(spResultDesc); spMapper->setPaddingValue(appData._paddingValue); spMapper->setImageInterpolator(generateInterpolator(appData._interpolatorType)); if (appData._noFailOnErrors) { spMapper->setThrowOnMappingError(false); spMapper->setErrorValue(appData._paddingValue); } spMapper->execute(); spResult = spMapper->getResultImage(); std::cout << "done." << std::endl; } catch (::itk::ExceptionObject& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e << std::endl; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; } catch (...) { std::cerr << "Error!!! Unkown error while mapping image." << std::endl; } return spResult; }; static typename PointSetType::Pointer doPointSetMapping(const ApplicationData& appData) { using TemplateImageType = ::itk::ImageBase; typedef map::core::Registration RegistrationType; typedef map::core::PointSetMappingTask MapperType; typename MapperType::Pointer spMapper = MapperType::New(); auto* pCastedInput = dynamic_cast(appData._input.GetPointer()); typename PointSetType::Pointer spResult; RegistrationType* pCastedReg = dynamic_cast(appData._spReg.GetPointer()); try { std::cout << std::endl << "map input file... "; spMapper->setInputPointSet(pCastedInput); spMapper->setRegistration(pCastedReg); if (appData._noFailOnErrors) { spMapper->setThrowOnMappingError(false); spMapper->setErrorPointValue(appData._paddingValue); } spMapper->execute(); spResult = spMapper->getResultPointSet(); std::cout << "done." << std::endl; } catch (::itk::ExceptionObject& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e << std::endl; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; } catch (...) { std::cerr << "Error!!! Unkown error while mapping image." << std::endl; } return spResult; }; static void processData(const ApplicationData& appData) { if (appData._inputIsImage) { typename ImageType::Pointer mappedImage = doMapping(appData); doWriting(mappedImage, appData); } else { typename PointSetType::Pointer mappedPoints = doPointSetMapping(appData); std::cout << std::endl << "save output file ... "; ::map::utilities::saveLandMarksToFile(appData._outputFileName, mappedPoints); std::cout << std::endl << "done"; } } }; } // namespace mapR } // namespace apps } // namespace map #endif diff --git a/Applications/Mapper/source/mapRApplicationData.cpp b/Applications/Mapper/source/mapRApplicationData.cpp index 16f8eb0..b4ffc3f 100644 --- a/Applications/Mapper/source/mapRApplicationData.cpp +++ b/Applications/Mapper/source/mapRApplicationData.cpp @@ -1,300 +1,300 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // 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. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL$ */ #include "mapRApplicationData.h" #include "mapConfigure.h" #include "itksys/SystemTools.hxx" namespace map { namespace apps { namespace mapR { int unknown_argument(const char* argument, void* call_data) { std::cout << "Got unknown argument: \"" << argument << "\"" << std::endl; return 0; } ApplicationData:: ApplicationData() { this->Reset(); } void ApplicationData:: Reset() { _inputFileName = ""; _outputFileName = ""; _regFileName = ""; _refFileName = ""; _logFileName = ""; _showVersion = false; _showHelp = false; _detailedOutput = false; _paddingValue = 0.0; _noFailOnErrors = false; _upperSeriesLimit = 0; - _loadedPixelType = ::itk::ImageIOBase::SCALAR; - _loadedComponentType = ::itk::ImageIOBase::UCHAR; + _loadedPixelType = ::itk::IOPixelEnum::SCALAR; + _loadedComponentType = ::itk::IOComponentEnum::UCHAR; _loadedDimensions = 1; _inputIsImage = true; _seriesReadStyle = io::ImageSeriesReadStyle::Default; _seriesWriteStyle = io::ImageSeriesReadStyle::Default; _seriesReadStyleStr = "default"; _seriesWriteStyleStr = ""; _interpolatorType = ImageMappingInterpolator::Linear; _interpolatorTypeStr = "linear"; _fileCount = 0; } unsigned int ApplicationData:: ParseArguments(int argc, char** argv) { this->Reset(); if (argc > 1) { ::map::core::String dummyArg = argv[1]; if (dummyArg.substr(0, 1) != "-") { //argument is the input file. Store the argument and move to next position. _inputFileName = dummyArg; ++_fileCount; --argc; ++argv; } } if (argc > 1) { ::map::core::String dummyArg = argv[1]; if (dummyArg.substr(0, 1) != "-") { //argument is the reg file. Store the argument and move to next position before parsing starts. _regFileName = dummyArg; ++_fileCount; --argc; ++argv; } } cmdParser.Initialize(argc, argv); cmdParser.SetUnknownArgumentCallback(unknown_argument); cmdParser.AddArgument("--output", itksys::CommandLineArguments::SPACE_ARGUMENT, &_outputFileName, "Specifies name and location of the output file. Default is the location of the input file and a name constructed from the name of the input file and the registration file."); cmdParser.AddArgument("-o", itksys::CommandLineArguments::SPACE_ARGUMENT, &_outputFileName, "Specifies name and location of the output file. Default is the location of the input file and a name constructed from the name of the input file and the registration file."); cmdParser.AddArgument("--FOVtemplate", itksys::CommandLineArguments::SPACE_ARGUMENT, &_refFileName, "Specifies name and location of the file that serves as template for the target field of view. Thus this file defines spacing, size, origin and orientation of the output image. Default is that the input image is used as template."); cmdParser.AddArgument("-t", itksys::CommandLineArguments::SPACE_ARGUMENT, &_refFileName, "Specifies name and location of the file that serves as template for the target field of view. Thus this file defines spacing, size, origin and orientation of the output image. Default is that the input image is used as template."); cmdParser.AddArgument("--padding", itksys::CommandLineArguments::SPACE_ARGUMENT, &_paddingValue, "Specifies the value that should be used for pixels of the result image that are not covered by the mapped input image. Default value is '0.0'."); cmdParser.AddArgument("-p", itksys::CommandLineArguments::SPACE_ARGUMENT, &_paddingValue, "Specifies the value that should be used for pixels of the result image that are not covered by the mapped input image. Default value is '0.0'."); cmdParser.AddArgument("-v", itksys::CommandLineArguments::NO_ARGUMENT, &_showVersion, "Shows the version of the program."); cmdParser.AddArgument("-d", itksys::CommandLineArguments::NO_ARGUMENT, &_detailedOutput, "Program has a more detailed (debug) output."); cmdParser.AddArgument("--details", itksys::CommandLineArguments::NO_ARGUMENT, &_detailedOutput, "Program has a more detailed (debug) output."); cmdParser.AddArgument("-h", itksys::CommandLineArguments::NO_ARGUMENT, &_showHelp, "Shows this help information for the program."); cmdParser.AddArgument("--help", itksys::CommandLineArguments::NO_ARGUMENT, &_showHelp, "Shows this help information for the program."); cmdParser.AddArgument("-?", itksys::CommandLineArguments::NO_ARGUMENT, &_showHelp, "Shows this help information for the program."); cmdParser.AddArgument("-u", itksys::CommandLineArguments::SPACE_ARGUMENT, &_upperSeriesLimit, "Only relevant in combination with numeric read style. Defines the upper index of the numeric image stack."); cmdParser.AddArgument("--upperSeriesLimit", itksys::CommandLineArguments::SPACE_ARGUMENT, &_upperSeriesLimit, "Only relevant in combination with numeric read style. Defines the upper index of the numeric image stack."); cmdParser.AddArgument("-r", itksys::CommandLineArguments::SPACE_ARGUMENT, &_seriesReadStyleStr, "Defines the read style for input and template image. Valid values are: 'default': like dicom but does not force series output; 'dicom': in current version it is equal to use 'gdcm'; 'gdcm': uses the dicom series file names reader and GDCM to load the images; 'none': only the specified file will be read; 'numeric': uses the numeric series file names reader and forces an output as series of 2D images."); cmdParser.AddArgument("--seriesReader", itksys::CommandLineArguments::SPACE_ARGUMENT, &_seriesReadStyleStr, "Defines the read style for input and template image. Valid values are: 'default': like dicom but does not force series output; 'dicom': in current version it is equal to use 'gdcm'; 'gdcm': uses the dicom series file names reader and GDCM to load the images; 'none': only the specified file will be read; 'numeric': uses the numeric series file names reader and forces an output as series of 2D images."); cmdParser.AddArgument("-w", itksys::CommandLineArguments::SPACE_ARGUMENT, &_seriesWriteStyleStr, "Defines the write style for the result image by overwriting the settings implied by the read style. Valid values are: 'default': output depends on the specified file format; 'dicom': uses the dicom series file names reader and forces an output as series of 2D images; 'gdcm': forces an output as series of 2D images; 'none': see default; 'numeric': forces an output as series of 2D images."); cmdParser.AddArgument("--seriesWriter", itksys::CommandLineArguments::SPACE_ARGUMENT, &_seriesWriteStyleStr, "Defines the write style for the result image by overwriting the settings implied by the read style. Valid values are: 'default': output depends on the specified file format; 'dicom': uses the dicom series file names reader and forces an output as series of 2D images; 'gdcm': further forces an output as series of 2D images; 'none': see default; 'numeric': forces an output as series of 2D images."); cmdParser.AddArgument("-i", itksys::CommandLineArguments::SPACE_ARGUMENT, &_interpolatorTypeStr, "Defines the interpolator that should be used for mapping the image. Default value is 'linear'. Valid values are: 'nn': uses a nearest neighbor interpolator; 'linear': uses a simple linear interpolator; 'bspline_3': uses a 3rd order B spline interpolator; 'hamming': uses a wsinc with hamming window as interpolator; 'welch': uses a wsinc with welch window as interpolator."); cmdParser.AddArgument("--interpolator", itksys::CommandLineArguments::SPACE_ARGUMENT, &_interpolatorTypeStr, "Defines the interpolator that should be used for mapping the image. Default value is 'linear'. Valid values are: 'nn': uses a nearest neighbor interpolator; 'linear': uses a simple linear interpolator; 'bspline_3': uses a 3rd order B spline interpolator; 'hamming': uses a wsinc with hamming window as interpolator; 'welch': uses a wsinc with welch window as interpolator."); cmdParser.AddArgument("--handleMappingFailure", itksys::CommandLineArguments::NO_ARGUMENT, &_noFailOnErrors, "If this flag is activated the mapping process will not faile if the registration is not sufficiently defined. Instead it will use the padding value (-p) to mark any voxel that could not be map due to the insufficent registration with the padding value."); cmdParser.AddArgument("--log", itksys::CommandLineArguments::SPACE_ARGUMENT, &_logFileName, "Specifies name and location of the log file. Default (flag not set) is that no log file is written."); cmdParser.AddArgument("-l", itksys::CommandLineArguments::SPACE_ARGUMENT, &_logFileName, "Specifies name and location of the log file. Default (flag not set) is that no log file is written."); if (cmdParser.Parse() == 0) { std::cerr << "Wrong command line option or insufficient number of arguments." << std::endl; std::cerr << "The last correct argument was: " << argv[cmdParser.GetLastArgument()] << std::endl << "Use one of the following flags for more information:" << std::endl; std::cerr << "-? or --help" << std::endl; return 3; }; if (_showHelp) { std::cout << std::endl << "Usage: " << std::endl << std::endl; std::cout << " mapR [] [options]" << std::endl << std::endl; std::cout << " Input: File path to the image that should be mapped." << std::endl; std::cout << " Reg: File path to the registration file that specifies" << std::endl; std::cout << " the registration that should be used for mapping." << std::endl; std::cout << " Optional: If no reg file is specified, an identity" << std::endl; std::cout << " transform will be used for mapping." << std::endl << std::endl; std::cout << "Command-Line Options:" << std::endl << std::endl; std::cout << cmdParser.GetHelp() << std::endl << std::endl; std::cout << " Example:" << std::endl << std::endl; std::cout << " mapR input.dcm reg.mapr -t target.dcm" << std::endl << std::endl; std::cout << R"( This will map "input.png" by using "reg.mapr". The field of view of the output image is defined by "target.dcm". The output will be in the directory of the input. The output file name will be "input_reg.dcm".)" << std::endl; return 1; } if (_showVersion) { std::cout << std::endl << "Version: " << MAP_FULL_VERSION_STRING << std::endl; return 1; } if (_fileCount < 1) { return 2; } if (_outputFileName.empty()) { ::map::core::String path = core::FileDispatch::getPath(_inputFileName); ::map::core::String inputName = core::FileDispatch::getName(_inputFileName); ::map::core::String inputExt = core::FileDispatch::getExtension(_inputFileName); ::map::core::String regName = core::FileDispatch::getName(_regFileName); _outputFileName = core::FileDispatch::createFullPath(path, inputName + "_" + regName + inputExt); } if (_seriesReadStyleStr == "none") { _seriesReadStyle = io::ImageSeriesReadStyle::None; } else if (_seriesReadStyleStr == "dicom") { _seriesReadStyle = io::ImageSeriesReadStyle::Dicom; } else if (_seriesReadStyleStr == "numeric") { _seriesReadStyle = io::ImageSeriesReadStyle::Numeric; } else if (_seriesReadStyleStr == "gdcm") { _seriesReadStyle = io::ImageSeriesReadStyle::GDCM; } if (!_seriesWriteStyleStr.empty()) { if (_seriesWriteStyleStr == "none") { _seriesWriteStyle = io::ImageSeriesReadStyle::None; } else if (_seriesWriteStyleStr == "dicom") { _seriesWriteStyle = io::ImageSeriesReadStyle::Dicom; } else if (_seriesWriteStyleStr == "numeric") { _seriesWriteStyle = io::ImageSeriesReadStyle::Numeric; } else if (_seriesWriteStyleStr == "gdcm") { _seriesWriteStyle = io::ImageSeriesReadStyle::GDCM; } } else { _seriesWriteStyle = _seriesReadStyle; _seriesWriteStyleStr = _seriesReadStyleStr; } if (_interpolatorTypeStr == "nn") { _interpolatorType = ImageMappingInterpolator::NearestNeighbor; } else if (_interpolatorTypeStr == "linear") { _interpolatorType = ImageMappingInterpolator::Linear; } else if (_interpolatorTypeStr == "bspline_3") { _interpolatorType = ImageMappingInterpolator::BSpline_3; } else if (_interpolatorTypeStr == "hamming") { _interpolatorType = ImageMappingInterpolator::WSinc_Hamming; } else if (_interpolatorTypeStr == "welch") { _interpolatorType = ImageMappingInterpolator::WSinc_Welch; } else { _interpolatorType = ImageMappingInterpolator::Unkown; } return 0; }; } // namespace mapR } // namespace apps } // namespace map diff --git a/Applications/Mapper/source/mapRHelper.cpp b/Applications/Mapper/source/mapRHelper.cpp index dc35219..91de1fe 100644 --- a/Applications/Mapper/source/mapRHelper.cpp +++ b/Applications/Mapper/source/mapRHelper.cpp @@ -1,259 +1,259 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // 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. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL$ */ #include "mapRHelper.h" #include "mapGenericImageReader.h" #include "mapDummyRegistrationAlgorithm.h" #include "mapSimpleLandMarkFileReader.h" map::apps::mapR::LoadingLogic::LoadingLogic(ApplicationData& appData): _appData(appData) { }; template map::core::RegistrationBase::Pointer GenerateDummyReg() { using DummyRegType = map::algorithm::DummyRegistrationAlgorithm; typename DummyRegType::Pointer regAlg = DummyRegType::New(); map::core::RegistrationBase::Pointer dummyReg = regAlg->getRegistration().GetPointer(); return dummyReg; } void map::apps::mapR::LoadingLogic:: loadRegistration() { map::io::RegistrationFileReader::LoadedRegistrationPointer spReg; if (_appData._regFileName.empty()) { std::cout << std::endl << "generate identity transform... "; if (_appData._loadedDimensions == 2) { spReg = GenerateDummyReg<2>(); } else if (_appData._loadedDimensions == 3) { spReg = GenerateDummyReg<3>(); } else { mapDefaultExceptionStaticMacro( << "Cannot generate identity transform. Dimensionality of loaded input image is not supported. LoadedDimensions: " << _appData._loadedDimensions); } std::cout << "done." << std::endl; } else { map::io::RegistrationFileReader::Pointer spRegReader = map::io::RegistrationFileReader::New(); std::cout << std::endl << "read registration file... "; spReg = spRegReader->read(_appData._regFileName); std::cout << "done." << std::endl; if (_appData._detailedOutput) { std::cout << std::endl << "Registration info:" << std::endl; _appData._spReg->Print(std::cout); std::cout << std::endl; } if (spReg->getMovingDimensions() != spReg->getTargetDimensions() || spReg->getMovingDimensions() != _appData._loadedDimensions) { mapDefaultExceptionStaticMacro( << "Loaded registration and loaded image have no equal dimensionality. Registration cannot be used to map the image."); } } _appData._spReg = spReg; }; ::itk::DataObject::Pointer loadGenericPointSet(const ::map::core::String& filename, unsigned int& loadedDimensions) { ::itk::DataObject::Pointer result; if (!(filename.empty())) { try { using PointSetType = ::map::core::continuous::Elements<2>::InternalPointSetType; result = ::map::utilities::loadLandMarksFromFile(filename).GetPointer(); loadedDimensions = 2; } catch (...) { } try { using PointSetType = ::map::core::continuous::Elements<3>::InternalPointSetType; result = ::map::utilities::loadLandMarksFromFile(filename).GetPointer(); loadedDimensions = 3; } catch (...) { } } return result; }; void map::apps::mapR::LoadingLogic:: loadInput() { map::io::GenericImageReader::GenericOutputImageType::Pointer loadedImage; unsigned int loadedDimensions = 0; - map::io::GenericImageReader::LoadedPixelType loadedPixelType = ::itk::ImageIOBase::UNKNOWNPIXELTYPE; - map::io::GenericImageReader::LoadedComponentType loadedComponentType = ::itk::ImageIOBase::UNKNOWNCOMPONENTTYPE; + map::io::GenericImageReader::LoadedPixelType loadedPixelType = ::itk::IOPixelEnum::UNKNOWNPIXELTYPE; + map::io::GenericImageReader::LoadedComponentType loadedComponentType = ::itk::IOComponentEnum::UNKNOWNCOMPONENTTYPE; map::io::GenericImageReader::MetaDataDictionaryArrayType loadedMetaDataDictArray; map::io::GenericImageReader::Pointer spReader = map::io::GenericImageReader::New(); spReader->setSeriesReadStyle(_appData._seriesReadStyle); spReader->setFileName(_appData._inputFileName); spReader->setUpperSeriesLimit(_appData._upperSeriesLimit); std::cout << std::endl << "read input file... "; ::map::core::String loadErrorString; try { loadedImage = spReader->GetOutput(loadedDimensions, loadedPixelType, loadedComponentType); loadedMetaDataDictArray = spReader->getMetaDictionaryArray(); } catch (const std::exception& e) { loadErrorString = e.what(); } if (loadedImage.IsNotNull()) { std::cout << "done." << std::endl; if (_appData._detailedOutput) { std::cout << "Input image info:" << std::endl; loadedImage->Print(std::cout); std::cout << std::endl; } - if (loadedPixelType != ::itk::ImageIOBase::SCALAR) + if (loadedPixelType != ::itk::IOPixelEnum::SCALAR) { mapDefaultExceptionStaticMacro(<< "Unsupported input image. Only simple scalar images are supported in this version."); } if (loadedDimensions < 2 || loadedDimensions > 3) { mapDefaultExceptionStaticMacro(<< "Unsupported input image. Only 2D and 3D images are supported in this version."); } _appData._input = loadedImage; _appData._inputIsImage = true; _appData._loadedDimensions = loadedDimensions; _appData._loadedPixelType = loadedPixelType; _appData._loadedComponentType = loadedComponentType; _appData._loadedMetaDataDictArray = loadedMetaDataDictArray; } else //*try to load simple point set { _appData._input = loadGenericPointSet(_appData._inputFileName, loadedDimensions); if (_appData._input.IsNotNull()) { std::cout << "Input point set info:" << std::endl; _appData._input->Print(std::cout); } _appData._loadedDimensions = loadedDimensions; _appData._inputIsImage = false; } if (_appData._input.IsNull()) { mapDefaultExceptionStaticMacro(<< " Unable to load input. File is not existing or has an unsupported format." << std::endl << "Error details: " << loadErrorString); } }; void map::apps::mapR::LoadingLogic:: loadReferenceImage() { if (!(_appData._refFileName.empty())) { map::io::GenericImageReader::GenericOutputImageType::Pointer loadedImage; unsigned int loadedDimensions; map::io::GenericImageReader::LoadedPixelType loadedPixelType; map::io::GenericImageReader::LoadedComponentType loadedComponentType; map::io::GenericImageReader::MetaDataDictionaryArrayType loadedMetaDataDictArray; map::io::GenericImageReader::Pointer spReader = map::io::GenericImageReader::New(); spReader->setSeriesReadStyle(_appData._seriesReadStyle); spReader->setFileName(_appData._refFileName); spReader->setUpperSeriesLimit(_appData._upperSeriesLimit); std::cout << std::endl << "read template file... "; loadedImage = spReader->GetOutput(loadedDimensions, loadedPixelType, loadedComponentType); loadedMetaDataDictArray = spReader->getMetaDictionaryArray(); if (loadedImage.IsNotNull()) { std::cout << "done." << std::endl; if (_appData._detailedOutput) { std::cout << "Input image info:" << std::endl; loadedImage->Print(std::cout); std::cout << std::endl; } } else { mapDefaultExceptionStaticMacro( << " Unable to load template image. File is not existing or has an unsupported format."); } if (loadedDimensions != _appData._spReg->getTargetDimensions()) { mapDefaultExceptionStaticMacro( << " Unsupported template image. Template image dimensions does not match registration."); } _appData._spRefImage = loadedImage; _appData._loadedRefMetaDataDictArray = loadedMetaDataDictArray; } }; diff --git a/Applications/Matcher/source/matchRHelper.cpp b/Applications/Matcher/source/matchRHelper.cpp index 011c3a0..6bca1bb 100644 --- a/Applications/Matcher/source/matchRHelper.cpp +++ b/Applications/Matcher/source/matchRHelper.cpp @@ -1,670 +1,670 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // 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. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1083 $ (last changed revision) // @date $Date: 2015-09-08 11:18:31 +0200 (Di, 08 Sep 2015) $ (last change date) // @author $Author: debusc $ (last changed by) // Subversion HeadURL: $HeadURL: https://svn.inet.dkfz-heidelberg.de/sbr/Sources/SBR-Projects/MatchPoint/trunk/Applications/Mapper/source/matchRHelper.cpp $ */ #include "matchRHelper.h" #include "mapGenericImageReader.h" #include "mapDeploymentDLLAccess.h" #include "mapDeploymentDLLHandle.h" #include "mapMetaProperty.h" #include "mapContinuousElements.h" #include "mapSimpleLandMarkFileReader.h" #include "itkDataObject.h" #include "itkCastImageFilter.h" #include "itkImageMaskSpatialObject.h" #include #include /**helper function that takes a string and splits it by a given delimeter*/ template void split(const ::map::core::String &s, char delim, Out result) { std::stringstream ss; ss.str(s); ::map::core::String item; while (std::getline(ss, item, delim)) { *(result++) = item; } } template void handleImageCast(const ::map::io::GenericImageReader::GenericOutputImageType* inputImage, ::map::io::GenericImageReader::GenericOutputImageType::Pointer& castedImage) { typedef ::itk::Image InputImageType; using CastedImageType = typename ::map::core::discrete::Elements::InternalImageType; typedef ::itk::CastImageFilter FilterType; const auto* input = dynamic_cast(inputImage); typename FilterType::Pointer caster = FilterType::New(); caster->SetInput(input); caster->Update(); typename CastedImageType::Pointer casted = caster->GetOutput(); castedImage = casted.GetPointer(); } template void handleGenericImageCast(map::io::GenericImageReader::LoadedComponentType loadedComponentType, const ::map::io::GenericImageReader::GenericOutputImageType* inputImage, ::map::io::GenericImageReader::GenericOutputImageType::Pointer& castedImage) { switch (loadedComponentType) { case ::itk::ImageIOBase::UCHAR: { handleImageCast(inputImage, castedImage); break; } case ::itk::ImageIOBase::CHAR: { handleImageCast(inputImage, castedImage); break; } case ::itk::ImageIOBase::USHORT: { handleImageCast(inputImage, castedImage); break; } case ::itk::ImageIOBase::SHORT: { handleImageCast(inputImage, castedImage); break; } case ::itk::ImageIOBase::UINT: { handleImageCast(inputImage, castedImage); break; } case ::itk::ImageIOBase::INT: { handleImageCast(inputImage, castedImage); break; } case ::itk::ImageIOBase::ULONG: { handleImageCast(inputImage, castedImage); break; } case ::itk::ImageIOBase::LONG: { handleImageCast(inputImage, castedImage); break; } case ::itk::ImageIOBase::FLOAT: { handleImageCast(inputImage, castedImage); break; } case ::itk::ImageIOBase::DOUBLE: { handleImageCast(inputImage, castedImage); break; } default: { mapDefaultExceptionStaticMacro(<< "The file uses a pixel component type that is not supported in this application."); } } } void ::map::apps::matchR::loadAlgorithm(::map::apps::matchR::ApplicationData& appData) { map::deployment::RegistrationAlgorithmBasePointer spAlgorithmBase = nullptr; std::cout << std::endl << "Load registration algorithm..." << std::endl; map::deployment::DLLHandle::Pointer spHandle = nullptr; spHandle = map::deployment::openDeploymentDLL(appData._algorithmFileName); if (spHandle.IsNull()) { mapDefaultExceptionStaticMacro(<< "Cannot open deployed registration algorithm file."); } std::cout << "... libary opened..." << std::endl; if (appData._detailedOutput) { std::cout << "Algorithm information: " << std::endl; spHandle->getAlgorithmUID().Print(std::cout, 2); std::cout << std::endl; } //Now load the algorthm from DLL spAlgorithmBase = map::deployment::getRegistrationAlgorithm(spHandle); if (spAlgorithmBase.IsNotNull()) { std::cout << "... done" << std::endl << std::endl; if (spAlgorithmBase->getMovingDimensions() != spAlgorithmBase->getTargetDimensions() || spAlgorithmBase->getMovingDimensions() != appData._loadedDimensions) { mapDefaultExceptionStaticMacro(<< "Loaded algorithm and loaded imagey have no equal dimensionality. Algorithm cannot be used to register the image."); } appData._algorithm = spAlgorithmBase; } else { mapDefaultExceptionStaticMacro(<< "Cannot create algorithm instance"); } }; void ::map::apps::matchR::loadMovingImage(::map::apps::matchR::ApplicationData& appData) { map::io::GenericImageReader::GenericOutputImageType::Pointer loadedImage; unsigned int loadedDimensions; map::io::GenericImageReader::LoadedPixelType loadedPixelType; map::io::GenericImageReader::LoadedComponentType loadedComponentType; map::io::GenericImageReader::MetaDataDictionaryArrayType loadedMetaDataDictArray; map::io::GenericImageReader::Pointer spReader = map::io::GenericImageReader::New(); spReader->setSeriesReadStyle(appData._seriesReadStyle); spReader->setFileName(appData._movingFileName); spReader->setUpperSeriesLimit(appData._upperSeriesLimit); std::cout << std::endl << "Read moving image file... "; loadedImage = spReader->GetOutput(loadedDimensions, loadedPixelType, loadedComponentType); loadedMetaDataDictArray = spReader->getMetaDictionaryArray(); if (loadedImage.IsNotNull()) { std::cout << "done." << std::endl; if (appData._detailedOutput) { std::cout << "Moving image info:" << std::endl; loadedImage->Print(std::cout); std::cout << std::endl; } } else { mapDefaultExceptionStaticMacro(<< " Unable to load moving image. File is not existing or has an unsupported format."); } - if (loadedPixelType != ::itk::ImageIOBase::SCALAR) + if (loadedPixelType != ::itk::IOPixelEnum::SCALAR) { mapDefaultExceptionStaticMacro(<< "Unsupported moving image. Only simple scalar images are supported in this version."); } if (loadedDimensions < 2 || loadedDimensions > 3) { mapDefaultExceptionStaticMacro(<< "Unsupported moving image. Only 2D and 3D images are supported in this version."); } else if(loadedComponentType == 2) { handleGenericImageCast<2>(loadedComponentType, loadedImage, loadedImage); } else { handleGenericImageCast<3>(loadedComponentType, loadedImage, loadedImage); } appData._spMovingImage = loadedImage; appData._loadedDimensions = loadedDimensions; }; void ::map::apps::matchR::loadTargetImage(::map::apps::matchR::ApplicationData& appData) { if (!(appData._targetFileName.empty())) { map::io::GenericImageReader::GenericOutputImageType::Pointer loadedImage; unsigned int loadedDimensions; map::io::GenericImageReader::LoadedPixelType loadedPixelType; map::io::GenericImageReader::LoadedComponentType loadedComponentType; map::io::GenericImageReader::MetaDataDictionaryArrayType loadedMetaDataDictArray; map::io::GenericImageReader::Pointer spReader = map::io::GenericImageReader::New(); spReader->setSeriesReadStyle(appData._seriesReadStyle); spReader->setFileName(appData._targetFileName); spReader->setUpperSeriesLimit(appData._upperSeriesLimit); std::cout << std::endl << "Read target file... "; loadedImage = spReader->GetOutput(loadedDimensions, loadedPixelType, loadedComponentType); loadedMetaDataDictArray = spReader->getMetaDictionaryArray(); if (loadedImage.IsNotNull()) { std::cout << "done." << std::endl; if (appData._detailedOutput) { std::cout << "Target image info:" << std::endl; loadedImage->Print(std::cout); std::cout << std::endl; } } else { mapDefaultExceptionStaticMacro(<< " Unable to load target image. File is not existing or has an unsupported format."); } if (loadedDimensions != appData._loadedDimensions) { mapDefaultExceptionStaticMacro(<< " Unsupported target image. target image dimensions does not match moving image."); } if (loadedComponentType == 2) { handleGenericImageCast<2>(loadedComponentType, loadedImage, loadedImage); } else { handleGenericImageCast<3>(loadedComponentType, loadedImage, loadedImage); } appData._spTargetImage = loadedImage; } }; ::itk::DataObject::Pointer loadGenericPointSet(const ::map::core::String& filename, unsigned int dim) { ::itk::DataObject::Pointer result; if (!(filename.empty())) { if (dim == 2) { using PointSetType = ::map::core::continuous::Elements<2>::InternalPointSetType; result = ::map::utilities::loadLandMarksFromFile(filename).GetPointer(); } else { using PointSetType = ::map::core::continuous::Elements<2>::InternalPointSetType; result = ::map::utilities::loadLandMarksFromFile(filename).GetPointer(); } } return result; }; void ::map::apps::matchR::loadTargetPointSet(::map::apps::matchR::ApplicationData& appData) { if (!(appData._targetPointSetFileName.empty())) { std::cout << std::endl << "Read target point set file... "; appData._genericTargetPointSet = loadGenericPointSet(appData._targetPointSetFileName, appData._loadedDimensions); if (appData._genericTargetPointSet.IsNotNull()) { std::cout << "done." << std::endl; } else { mapDefaultExceptionStaticMacro(<< " Unable to load target point set. File is not existing or has an unsupported format."); } } }; void ::map::apps::matchR::loadMovingPointSet(::map::apps::matchR::ApplicationData& appData) { if (!(appData._movingPointSetFileName.empty())) { std::cout << std::endl << "Read moving point set file... "; appData._genericMovingPointSet = loadGenericPointSet(appData._movingPointSetFileName, appData._loadedDimensions); if (appData._genericMovingPointSet.IsNotNull()) { std::cout << "done." << std::endl; } else { mapDefaultExceptionStaticMacro(<< " Unable to load moving point set. File is not existing or has an unsupported format."); } } }; template void handleMaskConvert(const ::map::io::GenericImageReader::GenericOutputImageType* inputImage, typename ::itk::ImageMaskSpatialObject::Pointer& mask) { typedef ::itk::Image InputImageType; typedef ::itk::Image::PixelType, IDimension> MaskImageType; typedef ::itk::CastImageFilter FilterType; using SpatialType = ::itk::ImageMaskSpatialObject; const auto* input = dynamic_cast(inputImage); typename FilterType::Pointer caster = FilterType::New(); caster->SetInput(input); caster->Update(); typename SpatialType::Pointer spatial = SpatialType::New(); spatial->SetImage(caster->GetOutput()); mask = spatial; } template void handleGenericMaskConvert(map::io::GenericImageReader::LoadedComponentType loadedComponentType, const ::map::io::GenericImageReader::GenericOutputImageType* inputImage, typename ::itk::ImageMaskSpatialObject::Pointer& mask) { switch (loadedComponentType) { case ::itk::ImageIOBase::UCHAR: { handleMaskConvert(inputImage, mask); break; } case ::itk::ImageIOBase::CHAR: { handleMaskConvert(inputImage, mask); break; } case ::itk::ImageIOBase::USHORT: { handleMaskConvert(inputImage, mask); break; } case ::itk::ImageIOBase::SHORT: { handleMaskConvert(inputImage, mask); break; } case ::itk::ImageIOBase::UINT: { handleMaskConvert(inputImage, mask); break; } case ::itk::ImageIOBase::INT: { handleMaskConvert(inputImage, mask); break; } case ::itk::ImageIOBase::ULONG: { handleMaskConvert(inputImage, mask); break; } case ::itk::ImageIOBase::LONG: { handleMaskConvert(inputImage, mask); break; } case ::itk::ImageIOBase::FLOAT: { handleMaskConvert(inputImage, mask); break; } case ::itk::ImageIOBase::DOUBLE: { handleMaskConvert(inputImage, mask); break; } default: { mapDefaultExceptionStaticMacro(<< "The file uses a pixel component type that is not supported in this application."); } } } ::itk::DataObject::Pointer loadGenericMask(const ::map::core::String& filename, const ::map::io::ImageSeriesReadStyle::Type& readStyle, unsigned int dim) { ::itk::DataObject::Pointer result; if (!(filename.empty())) { map::io::GenericImageReader::GenericOutputImageType::Pointer loadedImage; unsigned int loadedDimensions; map::io::GenericImageReader::LoadedPixelType loadedPixelType; map::io::GenericImageReader::LoadedComponentType loadedComponentType; map::io::GenericImageReader::Pointer spReader = map::io::GenericImageReader::New(); spReader->setSeriesReadStyle(readStyle); spReader->setFileName(filename); loadedImage = spReader->GetOutput(loadedDimensions, loadedPixelType, loadedComponentType); if (loadedImage.IsNotNull()) { if (loadedDimensions != dim) { mapDefaultExceptionStaticMacro(<< " Unable to load mask. Mask dimension differs from input images."); } if (loadedDimensions == 2) { ::itk::ImageMaskSpatialObject<2>::Pointer mask; handleGenericMaskConvert<2>(loadedComponentType, loadedImage, mask); result = mask.GetPointer(); } else { ::itk::ImageMaskSpatialObject<3>::Pointer mask; handleGenericMaskConvert<3>(loadedComponentType, loadedImage, mask); result = mask.GetPointer(); } } else { mapDefaultExceptionStaticMacro(<< " Unable to load mask. File is not existing or has an unsupported format."); } } return result; }; void ::map::apps::matchR::loadTargetMask(::map::apps::matchR::ApplicationData& appData) { if (!(appData._targetMaskFileName.empty())) { std::cout << std::endl << "Read target mask file... "; appData._genericTargetMask = loadGenericMask(appData._targetMaskFileName, appData._seriesReadStyle, appData._loadedDimensions); if (appData._genericTargetMask.IsNotNull()) { std::cout << "done." << std::endl; } else { mapDefaultExceptionStaticMacro(<< " Unable to load target mask. File is not existing or has an unsupported format."); } } }; void ::map::apps::matchR::loadMovingMask(::map::apps::matchR::ApplicationData& appData) { if (!(appData._movingMaskFileName.empty())) { std::cout << std::endl << "Read moving mask file... "; appData._genericMovingMask = loadGenericMask(appData._movingMaskFileName, appData._seriesReadStyle, appData._loadedDimensions); if (appData._genericMovingMask.IsNotNull()) { std::cout << "done." << std::endl; } else { mapDefaultExceptionStaticMacro(<< " Unable to load moving mask. File is not existing or has an unsupported format."); } } }; void ::map::apps::matchR::loadParameterMap(::map::apps::matchR::ApplicationData& appData) { for (const auto& iter : appData._parameterStrs) { auto pos = iter.find_first_of("="); ::map::core::String name = iter.substr(0, pos); ::map::core::String value; if (pos != ::map::core::String::npos) { value = iter.substr(pos + 1); } appData._parameterMap.insert(std::make_pair(name, value)); } }; /**Helper function that converts, if possible */ template bool checkNConvert(const ::map::core::String& valueStr, TElement& value) { try { value = map::core::convert::toValueGeneric(valueStr); return true; } catch (...) { } return false; }; /**Template specification for helper of itk::Array*/ template <> bool checkNConvert(const ::map::core::String& valueStr, ::itk::Array& value) { try { std::vector valueStrVector; split(valueStr, ' ', std::back_inserter(valueStrVector)); value.SetSize(valueStrVector.size()); unsigned int pos = 0; for (const auto& aValue : valueStrVector) { value[pos++] = map::core::convert::toValueGeneric(aValue); } return true; } catch (...) { } return false; }; template map::core::MetaPropertyBase::Pointer checkCastAndSetProp(const ::map::core::String& valueStr) { bool result = false; TValueType value; map::core::MetaPropertyBase::Pointer prop; if (checkNConvert(valueStr, value)) { prop = map::core::MetaProperty::New(value).GetPointer(); } return prop; }; ::map::core::MetaPropertyBase::Pointer map::apps::matchR::wrapMetaProperty(const ::map::algorithm::MetaPropertyInfo* pInfo, const ::map::core::String& valueStr) { map::core::MetaPropertyBase::Pointer metaProp; if (pInfo == nullptr) { return metaProp; } if (pInfo->getTypeInfo() == typeid(int)) { metaProp = checkCastAndSetProp(valueStr); } else if (pInfo->getTypeInfo() == typeid(unsigned int)) { metaProp = checkCastAndSetProp(valueStr); } else if (pInfo->getTypeInfo() == typeid(long)) { metaProp = checkCastAndSetProp(valueStr); } else if (pInfo->getTypeInfo() == typeid(unsigned long)) { metaProp = checkCastAndSetProp(valueStr); } else if (pInfo->getTypeInfo() == typeid(float)) { metaProp = checkCastAndSetProp(valueStr); } else if (pInfo->getTypeInfo() == typeid(double)) { metaProp = checkCastAndSetProp(valueStr); } else if (pInfo->getTypeInfo() == typeid(::itk::Array)) { metaProp = checkCastAndSetProp< ::itk::Array >(valueStr); } else if (pInfo->getTypeInfo() == typeid(bool)) { metaProp = checkCastAndSetProp< bool >(valueStr); } else if (pInfo->getTypeInfo() == typeid(::map::core::String)) { metaProp = map::core::MetaProperty::New(valueStr).GetPointer(); } return metaProp; }; diff --git a/Code/Core/include/mapFieldByFileLoadFunctor.tpp b/Code/Core/include/mapFieldByFileLoadFunctor.tpp index 73dcef4..d953570 100644 --- a/Code/Core/include/mapFieldByFileLoadFunctor.tpp +++ b/Code/Core/include/mapFieldByFileLoadFunctor.tpp @@ -1,275 +1,275 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // 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. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL$ */ #ifndef __MAP_FIELD_BY_FILE_LOAD_FUNCTOR_TPP #define __MAP_FIELD_BY_FILE_LOAD_FUNCTOR_TPP #include "mapFieldByFileLoadFunctor.h" #include "mapLogbookMacros.h" #include "mapRepresentationException.h" #include "mapGenericVectorFieldTransform.h" #include "itkImageFileReader.h" #include "itkImageIOFactory.h" #include "mapNULLVectorAwareLinearInterpolateImageFunction.h" namespace map { namespace core { namespace functors { /*! Helper class for a workaround. * right now we only support symmetric inversion. Must be implemented later on. * Template specialization allows the compiling of the code even in unsupported * cases. * @todo: Implement suitable solutions for unsymmetric cases (like VectorCombinationPolicy) */ template class FieldByFileLoadFunctorHelper { public: typedef typename ::itk::GenericVectorFieldTransform< ::map::core::continuous::ScalarType, VInputDimensions, VOutputDimensions> TransformType; using TransformPointer = typename TransformType::Pointer; typedef typename FieldByFileLoadFunctor::InFieldRepresentationType InFieldRepresentationType; static inline TransformPointer generate(const ::map::core::String& filePath, const InFieldRepresentationType* pInFieldRepresentation) { mapExceptionStaticMacro(ExceptionObject, << "Error unsymmetric field inversion not implemented yet."); return NULL; } }; template class FieldByFileLoadFunctorHelper < VDimensions, VDimensions > { public: typedef typename FieldByFileLoadFunctor::FieldType FieldType; typedef typename ::itk::GenericVectorFieldTransform< ::map::core::continuous::ScalarType, VDimensions, VDimensions> TransformType; using TransformPointer = typename TransformType::Pointer; typedef typename FieldByFileLoadFunctor::InFieldRepresentationType InFieldRepresentationType; static inline TransformPointer generate(const ::map::core::String& filePath, const InFieldRepresentationType* pInFieldRepresentation) { typedef ::itk::ImageFileReader< FieldType > FieldReaderType; typename FieldReaderType::Pointer spFieldReader = FieldReaderType::New(); typename FieldType::Pointer spField = NULL; try { spFieldReader->SetFileName(filePath.c_str()); spField = spFieldReader->GetOutput(); spFieldReader->Update(); } catch (itk::ExceptionObject& e) { e.SetDescription(String("Error in FieldByFileLoadFunctor while loading field. File name: ") + filePath + String(". Description: ") + e.GetDescription()); throw; } catch (const std::exception& e) { mapExceptionStaticMacro(ExceptionObject, << "Error in FieldByFileLoadFunctor while loading field. File name: " << filePath << ". Description: " << e.what()); } catch (...) { mapExceptionStaticMacro(ExceptionObject, << "Unknown error in FieldByFileLoadFunctor while loading field. File name: " << filePath); } /**@TODO Have to add check of the field representation (the specified one and the one set set in the functor.**/ //Superclass::_spInFieldRepresentation = createFieldRepresentation(*spField).GetPointer(); TransformPointer spResult = TransformType::New(); spResult->SetDisplacementField(spField); return spResult.GetPointer(); } }; template typename FieldByFileLoadFunctor::TransformPointer FieldByFileLoadFunctor:: generateTransform() const { mapLogInfoMacro(<< "Generate field by file loading. File name: " << _filePath); typedef typename FieldByFileLoadFunctorHelper::TransformType FieldTransformType; typename FieldTransformType::Pointer spResult = FieldByFileLoadFunctorHelper::generate(_filePath, Superclass::_spInFieldRepresentation); typedef typename ::itk::map::NULLVectorAwareLinearInterpolateImageFunction < typename FieldTransformType::GenericVectorFieldType, typename FieldTransformType::ScalarType> InterpolatorType; typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetNullVectorUsage(this->_useNullPoint); typename InterpolatorType::OutputType nullVector; typedef typename InterpolatorType::OutputType::Superclass VectorSuperclassType; nullVector.VectorSuperclassType::operator = (this->_nullPoint); interpolator->SetNullVector(nullVector); spResult->SetInterpolator(interpolator); spResult->SetUseNullPoint(this->_useNullPoint); spResult->SetNullPoint(this->_nullPoint); return spResult.GetPointer(); } template const String& FieldByFileLoadFunctor:: getFieldFilePath() const { return _filePath; } template typename FieldByFileLoadFunctor::Pointer FieldByFileLoadFunctor:: New(const String& filepath, const InFieldRepresentationType* pInFieldRepresentation) { Pointer spFieldByFileLoadFunctor = new Self(filepath, pInFieldRepresentation); spFieldByFileLoadFunctor->UnRegister(); return spFieldByFileLoadFunctor; } template typename ::itk::LightObject::Pointer FieldByFileLoadFunctor:: CreateAnother() const { ::itk::LightObject::Pointer smartPtr; smartPtr = Self::New(_filePath, Superclass::_spInFieldRepresentation).GetPointer(); return smartPtr; } template FieldByFileLoadFunctor:: FieldByFileLoadFunctor(const String& filepath, const InFieldRepresentationType* pInFieldRepresentation) : Superclass(pInFieldRepresentation), _filePath(filepath) { } template FieldByFileLoadFunctor:: ~FieldByFileLoadFunctor() {} template void FieldByFileLoadFunctor:: PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "File path: " << _filePath << std::endl; } } // end namespace functors template typename FieldRepresentationDescriptor::Pointer createFieldRepresentationOfMetaImageFile(const String& filePath) { if (filePath.empty()) { } if (!itksys::SystemTools::FileExists(filePath.c_str())) { mapExceptionStaticMacro(::itk::ImageFileReaderException, << "The file doesn't exist. Cannot create field description." << std::endl << "Filename = " << filePath); } - itk::ImageIOBase::Pointer spImageIO = itk::ImageIOFactory::CreateImageIO(filePath.c_str(), itk::ImageIOFactory::ReadMode); + itk::ImageIOBase::Pointer spImageIO = itk::ImageIOFactory::CreateImageIO(filePath.c_str(), itk::IOFileModeEnum::ReadMode); if (spImageIO.IsNull()) { mapExceptionStaticMacro(::itk::ImageFileReaderException, << "Cannot create field description. No image io available for field file." << std::endl << "Filename = " << filePath); } spImageIO->SetFileName(filePath); spImageIO->ReadImageInformation(); const unsigned int numberOfDimensionsIO = spImageIO->GetNumberOfDimensions(); if (numberOfDimensionsIO != VDimensions) { mapExceptionStaticMacro(DimRepresentationException, << "Cannot create field description. Invalid dimensionality. Dimension of meta image: " << numberOfDimensionsIO << "; expected Dimension: " << VDimensions); } typedef FieldRepresentationDescriptor FRDType; typename FRDType::PointType origin; typename FRDType::SizeType fieldSize; typename FRDType::SpacingType fieldSpacing; typename FRDType::DirectionType direction; for (unsigned int i = 0; i < VDimensions; i++) { fieldSpacing[i] = spImageIO->GetSpacing(i); fieldSize[i] = static_cast(spImageIO->GetDimensions( i) * fieldSpacing[i]); origin[i] = spImageIO->GetOrigin(i); // Please note: direction cosines are stored as columns of the // direction matrix std::vector axis; axis = spImageIO->GetDirection(i); for (unsigned j = 0; j < VDimensions; j++) { direction[j][i] = axis[j]; } } typename FRDType::Pointer spFRD = FRDType::New(); spFRD->setSpacing(fieldSpacing); spFRD->setSize(fieldSize); spFRD->setOrigin(origin); spFRD->setDirection(direction); return spFRD; }; } // end namespace core } // end namespace map #endif