/*!
* \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<MeasureType>
::Tomato(std::string inputFileName){
_nSamples = 0;
_invTimes = 0; // nullptr
_echoTimes = 0; // nullptr
_opts = new TomatoOptions<InputPixelType>(inputFileName);
_imageCalculatorItk = CalculatorT1ImageFilterType::New();
//_sorterMag = SortInvTimesImageFilterType::New();
//_sorterPha = SortInvTimesImageFilterType::New();
}
template< typename MeasureType >
Tomato<MeasureType>
::~Tomato(){
delete _opts;
delete [] _invTimes;
delete [] _echoTimes;
}
template< typename MeasureType >
int
Tomato<MeasureType>
::readAndSort(){
if (_opts->files_magnitude.size() > 0){
return readAndSortInputFileList();
}
else{
return readAndSortInputDirs();
}
}
template< typename MeasureType >
int
Tomato<MeasureType>
::readAndSortInputFileList(){
typename ReadFileListFilterType::Pointer readerMag = ReadFileListFilterType::New();
readerMag->SetFileList(_opts->files_magnitude);
readerMag->Update();
typename ReadFileListFilterType::Pointer readerPha = ReadFileListFilterType::New();
readerPha->SetFileList(_opts->files_phase);
readerPha->Update();
// have we read magnitudes?
if (readerMag->GetInvTimes().size() == 0){
throw std::runtime_error("No magnitude images read, check the paths!");
}
typename SortInvTimesImageFilterType::Pointer sorterMag = SortInvTimesImageFilterType::New();
sorterMag->SetInvTimesNonSorted(readerMag->GetInvTimes());
sorterMag->SetInput(readerMag->GetOutput());
sorterMag->Update();
typename SortInvTimesImageFilterType::Pointer sorterPha = SortInvTimesImageFilterType::New();
sorterPha->SetInvTimesNonSorted(readerPha->GetInvTimes());
sorterPha->SetInput(readerPha->GetOutput());
sorterPha->Update();
// are the inversion times in magnitude and phase series equal?
if (sorterMag->GetInvTimesSorted() == sorterPha->GetInvTimesSorted()){
vnl_vector<InputPixelType > temp = sorterMag->GetInvTimesSorted();
_nSamples = temp.size();
_invTimes = new InputPixelType[_nSamples];
KWUtil::copyArrayToArray(_nSamples, _invTimes, temp.data_block());
} else {
throw std::runtime_error("Mag and Pha inv times are not equal");
}
_dictionaryInput = readerMag->GetDicomIO()->GetMetaDataDictionary();
_imageMag = sorterMag->GetOutput();
_imagePha = sorterPha->GetOutput();
return 0; // EXIT_SUCCESS
}
template< typename MeasureType >
int
Tomato<MeasureType>
::readAndSortInputDirs(){
typename ReadDirectoryFilterType::Pointer readerMag = ReadDirectoryFilterType::New();
readerMag->SetDirName(_opts->dir_magnitude);
readerMag->Update();
typename ReadDirectoryFilterType::Pointer readerPha = ReadDirectoryFilterType::New();
readerPha->SetDirName(_opts->dir_phase);
readerPha->Update();
// have we read magnitudes?
if (readerMag->GetInvTimes().size() == 0){
throw std::runtime_error("No magnitude images read, check the paths!");
}
typename SortInvTimesImageFilterType::Pointer sorterMag = SortInvTimesImageFilterType::New();
sorterMag->SetInvTimesNonSorted(readerMag->GetInvTimes());
sorterMag->SetInput(readerMag->GetOutput());
sorterMag->Update();
typename SortInvTimesImageFilterType::Pointer sorterPha = SortInvTimesImageFilterType::New();
sorterPha->SetInvTimesNonSorted(readerPha->GetInvTimes());
sorterPha->SetInput(readerPha->GetOutput());
sorterPha->Update();
// are the inversion times in magnitude and phase series equal?
if (sorterMag->GetInvTimesSorted() == sorterPha->GetInvTimesSorted()){
vnl_vector<InputPixelType > temp = sorterMag->GetInvTimesSorted();
_nSamples = temp.size();
_invTimes = new InputPixelType[_nSamples];
KWUtil::copyArrayToArray(_nSamples, _invTimes, temp.data_block());
} else {
throw std::runtime_error("Mag and Pha inv times are not equal");
}
_dictionaryInput = readerMag->GetMetaDataDictionary();
_imageMag = sorterMag->GetOutput();
_imagePha = sorterPha->GetOutput();
return 0; // EXIT_SUCCESS
}
template< typename MeasureType >
int
Tomato<MeasureType>
::calculate() {
// alloc and init
CalculatorT1<InputPixelType> *calculatorT1 = FactoryOfCalculators<InputPixelType>::newByFactory(_opts);
FunctionsT1<InputPixelType> *functionsT1 = FactoryOfFunctions<InputPixelType>::newByFactory(_opts);
Fitter<InputPixelType> *fitter = FactoryOfFitters<InputPixelType>::newByFactory(_opts);
SignCalculator<InputPixelType> *signCalculator = FactoryOfSignCalculators<InputPixelType>::newByFactory(_opts);
StartPointCalculator<InputPixelType> *startPointCalculator = FactoryOfStartPointCalculators<InputPixelType>::newByFactory(_opts);
// configure calculator
calculatorT1->setFunctionsT1(functionsT1);
calculatorT1->setFitter(fitter);
calculatorT1->setSignCalculator(signCalculator);
calculatorT1->setStartPointCalculator(startPointCalculator);
calculatorT1->setInvTimes(_invTimes);
calculatorT1->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(calculatorT1);
// 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();
printf("Calculation time: %.4fs.\n", clock.GetTotal());
delete functionsT1;
delete fitter;
delete signCalculator;
delete startPointCalculator;
delete calculatorT1;
return 0; // EXIT_SUCCESS
}
template< typename MeasureType >
int
Tomato<MeasureType>
::visualise(){
#ifdef USE_VTK
// visual presentation of the results
if (_opts->visualise) {
// OxColorbarImageFilter
typedef itk::Colorbar2DImageFilter< ImageType2D > ColorbarImageFilterType;
typename ColorbarImageFilterType::Pointer ColorbarFilter = ColorbarImageFilterType::New();
ColorbarFilter->SetInput(_imageCalculatorItk->GetT1Image());
QuickView viewer;
viewer.AddImage(_imageCalculatorItk->GetT1Image(), true, "T1");
viewer.AddImage(ColorbarFilter->GetOutput(), true, "T1 with colorbar");
viewer.AddImage(_imageCalculatorItk->GetR2Image(), true, "R2");
viewer.AddImage(_imageCalculatorItk->GetAImage(), true, "A");
viewer.AddImage(_imageCalculatorItk->GetBImage(), true, "B");
viewer.AddImage(_imageCalculatorItk->GetT1starImage(), true, "T1*");
viewer.AddImage(_imageCalculatorItk->GetChiSqrtImage(), true, "ChiSqrt");
viewer.AddImage(_imageCalculatorItk->GetSNRImage(), true, "SNR");
viewer.AddImage(_imageCalculatorItk->GetNShmolliSamplesUsedImage(), true, "Number of Samples used in reconstruction");
viewer.AddImage(_imageCalculatorItk->GetSD_AImage(), true, "SD A");
viewer.AddImage(_imageCalculatorItk->GetSD_BImage(), true, "SD B");
viewer.AddImage(_imageCalculatorItk->GetSD_T1Image(), true, "SD T1");
//viewer.SetViewPortSize(500);
viewer.Visualize();
}
#else // USE_VTK
printf("Visualisation not possible: the project was configured not to use VTK. Install VTK and reconfigure the project in CMake.");
//throw itk::ExceptionObject(__FILE__, __LINE__, "Visualisation not possible: the project was configured not to use VTK. Install VTK and reconfigure the project in CMake.");
#endif // USE_VTK
return 0; // EXIT_SUCCESS
}
} // namespace Ox
#endif
#endif //Tomato_Tomato_H