/*! * \file Tomato.h * \author Konrad Werys * \date 2018/08/14 */ #ifndef Tomato_Tomato_HXX #define Tomato_Tomato_HXX #include "CmakeConfigForTomato.h" #ifdef USE_ITK namespace Ox { template< typename MeasureType > Tomato ::Tomato(std::string inputFileName){ _nSamples = 0; _invTimes = 0; // nullptr _echoTimes = 0; // nullptr _opts = new TomatoOptions(inputFileName); _imageCalculatorItk = CalculatorT1ImageFilterType::New(); //_sorterMag = SortInvTimesImageFilterType::New(); //_sorterPha = SortInvTimesImageFilterType::New(); } template< typename MeasureType > Tomato ::~Tomato(){ delete _opts; delete [] _invTimes; delete [] _echoTimes; } template< typename MeasureType > int Tomato ::readAndSort(){ typename ReadFileListFilterType::Pointer readerMag = ReadFileListFilterType::New(); readerMag->SetFileList(_opts->files_magnitude); readerMag->SetDirName(_opts->dir_magnitude); readerMag->Update(); // have we read magnitudes? if (readerMag->GetInvTimes().empty()){ throw std::runtime_error("\nNo magnitude images read, check the paths!"); } if (_opts->files_magnitude.empty()){ _opts->files_magnitude = readerMag->GetFileList(); } typename SortInvTimesImageFilterType::Pointer sorterMag = SortInvTimesImageFilterType::New(); sorterMag->SetInvTimesNonSorted(readerMag->GetInvTimes()); sorterMag->SetEchoTimesNonSorted(readerMag->GetEchoTimes()); sorterMag->SetInput(readerMag->GetOutput()); if (_opts->parameter_type == T1) { sorterMag->SortByInvTimes(); } else if (_opts->parameter_type == T2){ sorterMag->SortByEchoTimes(); } sorterMag->Update(); typename ReadFileListFilterType::Pointer readerPha = ReadFileListFilterType::New(); readerPha->SetFileList(_opts->files_phase); readerPha->SetDirName(_opts->dir_phase); readerPha->Update(); // is phase empty? if (readerPha->GetInvTimes().empty()) { if (_opts->sign_calc_method != NoSign){ std::cerr << "\nNo phase images read, setting the sign_calc_method to NoSign" << std::endl; _opts->sign_calc_method = NoSign; } } if (_opts->files_phase.empty()){ _opts->files_phase = readerPha->GetFileList(); } typename SortInvTimesImageFilterType::Pointer sorterPha = SortInvTimesImageFilterType::New(); if (_opts->sign_calc_method != NoSign) { sorterPha->SetInvTimesNonSorted(readerPha->GetInvTimes()); sorterPha->SetEchoTimesNonSorted(readerMag->GetEchoTimes()); sorterPha->SetInput(readerPha->GetOutput()); if (_opts->parameter_type == T1) { sorterPha->SortByInvTimes(); } else if (_opts->parameter_type == T2){ sorterPha->SortByEchoTimes(); } sorterPha->Update(); } // are the inversion times in magnitude and phase series equal? if (_opts->sign_calc_method != NoSign) { if (sorterMag->GetInvTimesSorted() != sorterPha->GetInvTimesSorted()) { throw std::runtime_error("\nMag and Pha inv times are not equal"); } } vnl_vector tempInv = sorterMag->GetInvTimesSorted(); _nSamples = (int)tempInv.size(); _invTimes = new InputPixelType[_nSamples]; KWUtil::copyArrayToArray(_nSamples, _invTimes, tempInv.data_block()); if (_opts->inversion_times.empty()){ _opts->inversion_times = std::vector(tempInv.begin(), tempInv.end()); } vnl_vector tempEcho = sorterMag->GetEchoTimesSorted(); _nSamples = (int)tempEcho.size(); _echoTimes = new InputPixelType[_nSamples]; KWUtil::copyArrayToArray(_nSamples, _echoTimes, tempEcho.data_block()); if (_opts->echo_times.empty()){ _opts->echo_times = std::vector(tempEcho.begin(), tempEcho.end()); } _dictionaryInput = readerMag->GetDicomIO()->GetMetaDataDictionary(); _imageMag = sorterMag->GetOutput(); if (_opts->sign_calc_method != NoSign) { _imagePha = sorterPha->GetOutput(); } return 0; // EXIT_SUCCESS } template< typename MeasureType > int Tomato ::calculate() { // alloc and init Calculator *calculator = FactoryOfCalculators::newByFactory(_opts); Model *model = FactoryOfModels::newByFactory(_opts); Fitter *fitter = FactoryOfFitters::newByFactory(_opts); SignCalculator *signCalculator = FactoryOfSignCalculators::newByFactory(_opts); StartPointCalculator *startPointCalculator = FactoryOfStartPointCalculators::newByFactory(_opts); // configure calculator calculator->setModel(model); calculator->setFitter(fitter); calculator->setSignCalculator(signCalculator); calculator->setStartPointCalculator(startPointCalculator); calculator->setInvTimes(_invTimes); calculator->setEchoTimes(_echoTimes); if (_opts->noise.size() > 0){ calculator->setNoise(&(_opts->noise)[0]); } calculator->setNSamples(_nSamples); // configure calculator itk filter //CalculatorT1ImageFilterType::Pointer _imageCalculatorItk = CalculatorT1ImageFilterType::New(); //_imageCalculatorItk = CalculatorT1ImageFilterType::New(); _imageCalculatorItk->SetInputMagImage(_imageMag); _imageCalculatorItk->SetInputPhaImage(_imagePha); if (_opts->number_of_threads > 0) _imageCalculatorItk->SetNumberOfThreads(_opts->number_of_threads); _imageCalculatorItk->SetCalculator(calculator); // calculations itk::TimeProbe clock; clock.Start(); try { _imageCalculatorItk->Update(); } catch( itk::ExceptionObject & err ) { std::cerr << "ExceptionObject caught !" << std::endl; std::cerr << err << std::endl; } clock.Stop(); _opts->calculation_time = clock.GetTotal(); printf("Calculation time: %.4fs.\n", clock.GetTotal()); delete model; delete fitter; delete signCalculator; delete startPointCalculator; delete calculator; return 0; // EXIT_SUCCESS } template< typename MeasureType > int Tomato ::exportToDicom(){ if (_opts->parameter_type == Ox::T1){ return exportT1ToDicom(); } else if (_opts->parameter_type == Ox::T2){ return exportT2ToDicom(); } else { std::cerr << "Tomato::exportToDicom: Export has not been implemented" << std::endl; return 0; // EXIT_FAILURE } } template< typename IType, typename EType > class CastPixelAccessor { public: typedef IType InternalType; typedef EType ExternalType; static void Set(InternalType & output, const ExternalType & input) { output = static_cast( input ); } static ExternalType Get( const InternalType & input ) { return static_cast( input ); } }; } // namespace Ox #endif #endif //Tomato_Tomato_H