Commit d58b2ceb authored by Mathias Goldau's avatar Mathias Goldau

[ADD] This new module provides some scalar measures for diffusion tensors,...

[ADD] This new module provides some scalar measures for diffusion tensors, such as FA, RA, RD, MD, AD and the trace.
parent 3fa457e8
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2015 OpenWalnut Community, Nemtics, BSV@Uni-Leipzig
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include "WAD.h"
WAD::WAD()
: WObjectNDIP< WDataSetDTIToScalar_I >( "AD (Axial Diffusivity)", "Computes the AD of the tensor" )
{
}
double WAD::tensorToScalar( const WVector3d& evals, const WTensorSym< 2, 3, float >& /* tensor */ )
{
return evals[0];
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2015 OpenWalnut Community, Nemtics, BSV@Uni-Leipzig
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WAD_H
#define WAD_H
#include "core/common/math/linearAlgebra/WVectorFixed.h"
#include "core/common/math/WTensorSym.h"
#include "core/common/WObjectNDIP.h"
#include "WDataSetDTIToScalar_I.h"
/**
* Computes the AD (Axional Diffusivity) of a given Tensor.
* \f[
* AD = \lambda_1
* \f]
*/
class WAD : public WObjectNDIP< WDataSetDTIToScalar_I >
{
public:
/**
* Creates an object to perform the computation.
*/
WAD();
protected:
/**
* Actual AD computation takes place inhere.
*
* \param evals With the three given Eigenvalues, we may compute the AD. See the wikipedia article above for the formula.
* \param tensor Although not needed for AD computation, the API requires us to use the signature.
*
* \return The AD of the tensor.
*/
virtual double tensorToScalar( const WVector3d& evals, const WTensorSym< 2, 3, float >& tensor );
};
#endif // WAD_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2015 OpenWalnut Community, Nemtics, BSV@Uni-Leipzig
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <vector>
#include "core/common/WFlag.h"
#include "core/common/WLogger.h"
#include "core/common/WProgress.h"
#include "core/dataHandler/WDataSetDTI.h"
#include "core/dataHandler/WDataSetScalar.h"
#include "core/dataHandler/WDataSetVector.h"
#include "WDataSetDTIToScalar_I.h"
WDataSetDTIToScalar_I::~WDataSetDTIToScalar_I()
{
}
WDataSetScalar::SPtr WDataSetDTIToScalar_I::operator()( WProgress::SPtr progress, WBoolFlag const &shutdown,
WDataSetDTI::SPtr tensors, WDataSetVector::SPtr evals )
{
wlog::debug( "WDataSetDTIToScalar_I" ) << "Start computation";
typedef double ValueType;
typedef WValueSet< ValueType > ValueSetType;
boost::shared_ptr< WGrid > grid( evals->getGrid() );
boost::shared_ptr< std::vector< ValueType > > data( new std::vector< ValueType >( grid->size() ) );
boost::shared_ptr< WValueSet< float > > t = boost::dynamic_pointer_cast< WValueSet< float > >( tensors->getValueSet() );
WAssert( t, "Error: Only tensor data sets with doubles are allowed currently." );
for( unsigned int i = 0; i < grid->size() && !shutdown; ++i )
{
WTensorSym< 2, 3, float > tensor( t->getWValue( i ) );
WVector3d ev = evals->getVectorAt( i );
(*data)[i] = tensorToScalar( ev, tensor );
++*progress;
}
if( shutdown )
{
return WDataSetScalar::SPtr( new WDataSetScalar() ); // incase we had to abort due to shutdown, empty result
}
wlog::debug( "WDataSetDTIToScalar_I" ) << "Computation done.";
boost::shared_ptr< ValueSetType > vals( new ValueSetType( 0, 1, data ) );
return WDataSetScalar::SPtr( new WDataSetScalar( vals, grid ) );
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2015 OpenWalnut Community, Nemtics, BSV@Uni-Leipzig
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WDATASETDTITOSCALAR_I_H
#define WDATASETDTITOSCALAR_I_H
#include "core/common/math/linearAlgebra/WVectorFixed.h"
#include "core/common/math/WTensorSym.h"
#include "core/common/WFlag.h"
#include "core/common/WProgress.h"
#include "core/dataHandler/WDataSetDTI.h"
#include "core/dataHandler/WDataSetScalar.h"
#include "core/dataHandler/WDataSetVector.h"
/**
* Interface to compute various measures on tensors. Prominent examples are the
* Fractional Anisotropy (FA), trace, Relative Anisotropy, Mean Diffusivity, Radial Diffusivity, etc.
* As many scalar measures may use either the tensor components directly or rely on derived
* measures such as eigenvalues, both are needed for generating the scalar.
*/
class WDataSetDTIToScalar_I
{
public:
/**
* This runs the given strategy on the given dataset.
*
* \param progress the progress instance you should increment each time you fill the value for one voxel.
* \param shutdown Possibility to abort in case of shutdown.
* \param tensors The tensor components
* \param evals The Eigenvalues
*
* \return The scalar dataset, for which each tensor a scalar value is derived according to the subclass implementation.
*/
virtual WDataSetScalar::SPtr operator()( WProgress::SPtr progress, WBoolFlag const &shutdown,
WDataSetDTI::SPtr tensors, WDataSetVector::SPtr evals );
/**
* Destructor
*/
virtual ~WDataSetDTIToScalar_I();
protected:
/**
* Actual scalar computation.
*
* \param evals Eigenvalues
* \param tensor Tensor components
*
* \return Scalar value derived either from tensor components, eigenvalues or both.
*/
virtual double tensorToScalar( const WVector3d& evals, const WTensorSym< 2, 3, float >& tensor ) = 0;
};
#endif // WDATASETDTITOSCALAR_I_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2015 OpenWalnut Community, Nemtics, BSV@Uni-Leipzig
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <cmath>
#include "WFA.h"
WFA::WFA()
: WObjectNDIP< WDataSetDTIToScalar_I >( "FA (Fractional Anisotropy)", "Computes the FA of the tensor" )
{
}
double WFA::tensorToScalar( const WVector3d& evals, const WTensorSym< 2, 3, float >& /* tensor */ )
{
const WVector3d& l = evals; // shorthand (name) for lambda_1,...
double mean = ( l[0] + l[1] + l[2] ) / 3.0;
double nom = ( l[0] - mean ) * ( l[0] - mean ) + ( l[1] - mean ) * ( l[1] - mean ) + ( l[2] - mean ) * ( l[2] - mean );
double denom = l[0] * l[0] + l[1] * l[1] + l[2] * l[2];
return std::sqrt( 1.5 * nom / denom );
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2015 OpenWalnut Community, Nemtics, BSV@Uni-Leipzig
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WFA_H
#define WFA_H
#include "core/common/math/linearAlgebra/WVectorFixed.h"
#include "core/common/math/WTensorSym.h"
#include "core/common/WObjectNDIP.h"
#include "WDataSetDTIToScalar_I.h"
/**
* Computes the FA (Fractional Anisotropy, see: https://en.wikipedia.org/wiki/Fractional_anisotropy) of a given Tensor.
* \f[
* \hat{\lambda} = \frac{1}{3} \sum \lambda_i
* \f]
*
* \f[
* FA = \sqrt{ \frac{3}{2}
* \frac{ \left(\lambda_1 - \hat{\lambda} \right)^2 + \left(\lambda_2 - \hat{\lambda} \right)^2 +
* \left(\lambda_3 - \hat{\lambda} \right)^2 }
* {\lambda_1^2 + \lambda_2^2 + \lambda_3^2 }
* }
* \f]
*/
class WFA : public WObjectNDIP< WDataSetDTIToScalar_I >
{
public:
/**
* Creates an object to perform the computation.
*/
WFA();
protected:
/**
* Actual FA computation takes place inhere.
*
* \param evals With the three given Eigenvalues, we may compute the FA. See the wikipedia article above for the formula.
* \param tensor Although not needed for FA computation, the API requires us to use the signature.
*
* \return The FA of the tensor.
*/
virtual double tensorToScalar( const WVector3d& evals, const WTensorSym< 2, 3, float >& tensor );
};
#endif // WFA_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2015 OpenWalnut Community, Nemtics, BSV@Uni-Leipzig
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <cmath>
#include "WMD.h"
WMD::WMD()
: WObjectNDIP< WDataSetDTIToScalar_I >( "MD (Mean Diffusivity)", "Computes the MD of the tensor" )
{
}
double WMD::tensorToScalar( const WVector3d& evals, const WTensorSym< 2, 3, float >& /* tensor */ )
{
return 1.0/3.0 * ( evals[0] + evals[1] + evals[2] );
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2015 OpenWalnut Community, Nemtics, BSV@Uni-Leipzig
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WMD_H
#define WMD_H
#include "core/common/math/linearAlgebra/WVectorFixed.h"
#include "core/common/math/WTensorSym.h"
#include "core/common/WObjectNDIP.h"
#include "WDataSetDTIToScalar_I.h"
/**
* Computes the MD (Mean Diffusivity) of a given Tensor.
* \f[
* MD = \frac{1}{3}\sum_{i=1}^{3} \lambda_i
* \f]
*/
class WMD : public WObjectNDIP< WDataSetDTIToScalar_I >
{
public:
/**
* Creates an object to perform the computation.
*/
WMD();
protected:
/**
* Actual MD computation takes place inhere.
*
* \param evals With the three given Eigenvalues, we may compute the MD. See the wikipedia article above for the formula.
* \param tensor Although not needed for MD computation, the API requires us to use the signature.
*
* \return The MD of the tensor.
*/
virtual double tensorToScalar( const WVector3d& evals, const WTensorSym< 2, 3, float >& tensor );
};
#endif // WMD_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2015 OpenWalnut Community, Nemtics, BSV@Uni-Leipzig
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <string>
#include "core/kernel/WModuleFactory.h"
#include "WMDiffTensorScalars.h"
#include "WTensorTrace.h"
#include "WFA.h"
#include "WRA.h"
#include "WRD.h"
#include "WMD.h"
#include "WAD.h"
W_LOADABLE_MODULE( WMDiffTensorScalars )
WMDiffTensorScalars::WMDiffTensorScalars()
: WModuleContainer( "Diffusion Tensor Scalars", "Computes various scalar measures for a given diffusion tensor field (2nd order)." ),
m_strategy( "Scalar indices derived from tensors.", "Select one algorithm" )
{
m_strategy.addStrategy( WTensorTrace::SPtr( new WFA() ) );
m_strategy.addStrategy( WTensorTrace::SPtr( new WRA() ) );
m_strategy.addStrategy( WTensorTrace::SPtr( new WAD() ) );
m_strategy.addStrategy( WTensorTrace::SPtr( new WMD() ) );
m_strategy.addStrategy( WTensorTrace::SPtr( new WRD() ) );
m_strategy.addStrategy( WTensorTrace::SPtr( new WTensorTrace() ) );
}
WMDiffTensorScalars::~WMDiffTensorScalars()
{
}
boost::shared_ptr< WModule > WMDiffTensorScalars::factory() const
{
return boost::shared_ptr< WModule >( new WMDiffTensorScalars() );
}
void WMDiffTensorScalars::connectors()
{
m_tensorsIC = WModuleInputForwardData< WDataSetDTI >::createAndAdd( shared_from_this(), "tensorInput",
"DataSetDTI storing the tensor field" );
// math: I do not know how to hide this connector in network editor, as it is for internal use only
m_evalsIC = WModuleInputData< WDataSetVector >::createAndAdd( shared_from_this(), "eigenValues",
"EigenValues from the internal ÉigenSystem module" );
m_scalarOC = WModuleOutputData< WDataSetScalar >::createAndAdd( shared_from_this(), "scalars",
"The computed scalar dataset derived from the given tensor dataset" );
WModule::connectors();
}
void WMDiffTensorScalars::properties()
{
m_properties->addProperty( m_strategy.getProperties() );
WModule::properties();
}
void WMDiffTensorScalars::moduleMain()
{
initSubModules();
m_moduleState.setResetable( true, true );
m_moduleState.add( m_strategy.getProperties()->getUpdateCondition() );
// math: for several measures we need the eigenvalues from our submodule. Once they are computed
// we need to proceed. Hence we need the dataChanged condition in our module state. But beware
// there is also the tensor data input giving us events for the module main loop.
m_moduleState.add( m_eigenSystem->getOutputConnector( "evalsOutput" )->getDataChangedCondition() );
ready();
while( !m_shutdownFlag() )
{
debugLog() << "Waiting...";
m_moduleState.wait();
boost::shared_ptr< WModuleOutputConnector > evalConnector = m_eigenSystem->getOutputConnector( "evalsOutput" );
typedef WModuleOutputData< WDataSetVector > OCType;
boost::shared_ptr< OCType > evalsOC = boost::dynamic_pointer_cast< OCType >( evalConnector );
if( evalsOC )
{
m_evals = evalsOC->getData();
m_tensors = m_tensorsIC->getData();
}
if( !m_tensors || !m_evals )
{
continue;
}
// Strategy anwenden
debugLog() << "Start computing scalars...";
WProgress::SPtr progress( new WProgress( "Creating Dataset", m_evals->getGrid()->size() ) );
m_progress->addSubProgress( progress );
m_scalarOC->updateData( m_strategy()->operator()( progress, m_shutdownFlag, m_tensors, m_evals ) );
progress->finish();
m_progress->removeSubProgress( progress );
debugLog() << "Created scalar data done";
if( m_shutdownFlag() )
{
break;
}
}
}
void WMDiffTensorScalars::initSubModules()
{
// instantiation
m_eigenSystem = WModuleFactory::getModuleFactory()->create( WModuleFactory::getModuleFactory()->getPrototypeByName(
"Eigen System" ) ); // NOLINT
add( m_eigenSystem );
m_eigenSystem->isReady().wait();
// wiring
debugLog() << "Start wiring";
m_tensorsIC->forward( m_eigenSystem->getInputConnector( "tensorInput" ) );
debugLog() << "Wiring done";
// add proporties of submodules
m_properties->addPropertyGroup( "EigenSystem", "Props" )->addProperty( m_eigenSystem->getProperties() );
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2015 OpenWalnut Community, Nemtics, BSV@Uni-Leipzig
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WMDIFFTENSORSCALARS_H
#define WMDIFFTENSORSCALARS_H
#include <string>
#include <boost/shared_ptr.hpp>
#include "core/common/WObjectNDIP.h"
#include "core/common/WStrategyHelper.h"