Revision a763b81ee81810f5fa544165d5053bde478b2dbd authored by Konrad Werys on 28 November 2019, 13:47:50 UTC, committed by Konrad Werys on 28 November 2019, 13:47:50 UTC
1 parent e3f0532
Raw File
Tomato.hxx
/*!
 * \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(){

        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<InputPixelType > 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<InputPixelType >(tempInv.begin(), tempInv.end());
        }

        vnl_vector<InputPixelType > 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<InputPixelType >(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<MeasureType>
    ::calculate() {

        // alloc and init
        Calculator<InputPixelType> *calculator = FactoryOfCalculators<InputPixelType>::newByFactory(_opts);
        Model<InputPixelType> *model = FactoryOfModels<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
        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<MeasureType>
    ::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<InternalType>( input );
        }

        static ExternalType Get( const InternalType & input )
        {
            return static_cast<ExternalType>( input );
        }
    };

} // namespace Ox

#endif

#endif //Tomato_Tomato_H
back to top