Commit 0c5e9fdb authored by cornimueller's avatar cornimueller
Browse files

[ADD #97] Extracts orientation information from NIfTI files and passes them to WGridRegular3D

parent 8e960126
......@@ -22,13 +22,11 @@
//
//---------------------------------------------------------------------------
#include "../math/WPosition.h"
#include "../math/WVector3D.h"
#include "WGridRegular3D.h"
using wmath::WVector3D;
using wmath::WPosition;
using wmath::WMatrix;
WGridRegular3D::WGridRegular3D( double originX, double originY, double originZ,
unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
......@@ -44,6 +42,23 @@ WGridRegular3D::WGridRegular3D( double originX, double originY, double originZ,
{
}
WGridRegular3D::WGridRegular3D( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
const WMatrix< double >& mat )
: WGrid( nbPosX * nbPosY * nbPosZ ),
m_nbPosX( nbPosX ), m_nbPosY( nbPosY ), m_nbPosZ( nbPosZ )
{
assert( mat.getNbRows() == 4 && mat.getNbCols() == 4 );
// only affine transformations are allowed
assert( mat( 3, 0 ) == 0.0 && mat( 3, 1 ) == 0.0 && mat( 3, 2 ) == 0.0 );
m_origin = WPosition( mat( 0, 3 ) / mat( 3, 3 ), mat( 1, 3 ) / mat( 3, 3 ), mat( 2, 3 ) / mat( 3, 3 ) );
m_directionX = WVector3D( mat( 0, 0 ) / mat( 3, 3 ), mat( 1, 0 ) / mat( 3, 3 ), mat( 2, 0 ) / mat( 3, 3 ) );
m_directionY = WVector3D( mat( 0, 1 ) / mat( 3, 3 ), mat( 1, 1 ) / mat( 3, 3 ), mat( 2, 1 ) / mat( 3, 3 ) );
m_directionZ = WVector3D( mat( 0, 2 ) / mat( 3, 3 ), mat( 1, 2 ) / mat( 3, 3 ), mat( 2, 2 ) / mat( 3, 3 ) );
}
WGridRegular3D::WGridRegular3D( double originX, double originY, double originZ,
unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
double offsetX, double offsetY, double offsetZ )
......
......@@ -27,6 +27,7 @@
#include "../math/WPosition.h"
#include "../math/WVector3D.h"
#include "../math/WMatrix.hpp"
#include "WGrid.h"
......@@ -51,6 +52,17 @@ public:
const wmath::WVector3D& directionY,
const wmath::WVector3D& directionZ );
/**
* Defines the number of samples in each coordinate direction as ints,
* and the position of the origin of the grid and the offset between the
* samples in the different coordinate directions as one 4x4 transformation
* matrix using homogeneous coordinates (but only affine transformations are
* allowed).
*/
WGridRegular3D(
unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
const wmath::WMatrix< double >& mat );
/**
* Defines the position of the origin of the grid, the number of
* samples in each coordinate direction and the offset between the
......@@ -113,6 +125,28 @@ public:
return m_directionZ.norm();
}
/**
* Returns the vector determining the direction of samples in x direction.
*/
const wmath::WVector3D& getDirectionX() const
{
return m_directionX;
}
/**
* Returns the vector determining the direction of samples in y direction.
*/
const wmath::WVector3D& getDirectionY() const
{
return m_directionY;
}
/**
* Returns the vector determining the direction of samples in z direction.
*/
const wmath::WVector3D& getDirectionZ() const
{
return m_directionZ;
}
/**
* Returns the position of the origin of the grid.
*/
......
......@@ -60,6 +60,20 @@ template< typename T > std::vector< T > WLoaderNIfTI::copyArray( const T* dataAr
}
wmath::WMatrix< double > WLoaderNIfTI::convertMatrix( const mat44& in )
{
wmath::WMatrix< double > out( 4, 4 );
for( size_t i = 0; i < 4; ++i )
{
for( size_t j = 0; j < 4; ++j )
{
out( i, j ) = in.m[i][j];
}
}
return out;
}
void WLoaderNIfTI::operator()()
{
nifti_image* header = nifti_image_read( m_fileName.c_str(), 0 );
......@@ -85,17 +99,15 @@ void WLoaderNIfTI::operator()()
std::vector< int8_t > data =
copyArray( reinterpret_cast< int8_t* >( filedata->data ), nbValues, vDim );
newValueSet = boost::shared_ptr< WValueSetBase >( new WValueSet< int8_t >( 0, vDim, data, W_DT_INT8 ) );
newGrid = boost::shared_ptr< WGridRegular3D >( new WGridRegular3D( columns, rows, frames, 1., 1., 1. ) );
break;
}
case DT_SIGNED_SHORT:
{
std::vector< int16_t > data =
copyArray( reinterpret_cast< int16_t* >( filedata->data ), nbValues, vDim );
newValueSet = boost::shared_ptr< WValueSetBase >( new WValueSet< int16_t >( 0, vDim, data, W_DT_INT16 ) );
newGrid = boost::shared_ptr< WGridRegular3D >( new WGridRegular3D( columns, rows, frames, 1., 1., 1. ) );
break;
std::vector< int16_t > data =
copyArray( reinterpret_cast< int16_t* >( filedata->data ), nbValues, vDim );
newValueSet = boost::shared_ptr< WValueSetBase >( new WValueSet< int16_t >( 0, vDim, data, W_DT_INT16 ) );
break;
}
case DT_FLOAT:
......@@ -103,14 +115,31 @@ void WLoaderNIfTI::operator()()
std::vector< float > data =
copyArray( reinterpret_cast< float* >( filedata->data ), nbValues, vDim );
newValueSet = boost::shared_ptr< WValueSetBase >( new WValueSet< float >( 0, vDim, data, W_DT_FLOAT ) );
newGrid = boost::shared_ptr< WGridRegular3D >( new WGridRegular3D( columns, rows, frames, 1., 1., 1. ) );
break;
}
default:
std::cout << "unknown data type " << header->datatype << std::endl;
newValueSet = boost::shared_ptr< WValueSetBase >();
newGrid = boost::shared_ptr< WGrid >();
}
if( header->sform_code > 0 )
{
// method 3 (affine transform)
newGrid = boost::shared_ptr< WGridRegular3D >( new WGridRegular3D(
columns, rows, frames, convertMatrix( header->sto_xyz ) ) );
}
else if( header->qform_code > 0 )
{
// method 2 (rigid body transform)
newGrid = boost::shared_ptr< WGridRegular3D >( new WGridRegular3D(
columns, rows, frames, convertMatrix( header->qto_xyz ) ) );
}
else
{
// method 1 (only scaling)
newGrid = boost::shared_ptr< WGridRegular3D >( new WGridRegular3D(
columns, rows, frames, header->dx, header->dy, header->dz ) );
}
// TODO(wiebel): fill this info into the subject instead
......
......@@ -30,6 +30,7 @@
#include <boost/shared_ptr.hpp>
#include "../WLoader.h"
#include "../../math/WMatrix.hpp"
#include "nifti/nifti1_io.h"
......@@ -61,6 +62,12 @@ private:
* by niftilibio into a std::vector< T >
*/
template < typename T > std::vector< T > copyArray( const T* dataArray, const size_t nbValues, const size_t vDim );
/**
* This function converts a 4x4 matrix from the NIfTI libs into the format
* used by OpenWalnut.
*/
wmath::WMatrix< double > convertMatrix( const mat44& in );
};
#endif // WLOADERNIFTI_H
......@@ -28,10 +28,10 @@
#include <cxxtest/TestSuite.h>
#include "../WGridRegular3D.h"
#include "../../math/WVector3D.h"
using wmath::WVector3D;
using wmath::WPosition;
using wmath::WMatrix;
namespace CxxTest
{
......@@ -75,6 +75,7 @@ public:
TS_ASSERT_THROWS_NOTHING( WGridRegular3D grid( 0., 0., 0., 3, 3, 3, 1., 1., 1. ) );
TS_ASSERT_THROWS_NOTHING( WGridRegular3D grid( 0., 0., 0., 3, 3, 3,
WVector3D( 3., 1., 2. ), WVector3D( 1., 3., 2. ), WVector3D( 1., 2., 3. ) ) );
TS_ASSERT_THROWS_NOTHING( WGridRegular3D grid( 3, 3, 3, WMatrix< double >( 4, 4 ) ) );
}
/**
......@@ -91,6 +92,9 @@ public:
WGridRegular3D grid3( 0., 0., 0., 3, 3, 3,
WVector3D( 3., 1., 2. ), WVector3D( 1., 3., 2. ), WVector3D( 1., 2., 3. ) );
TS_ASSERT_EQUALS( grid3.size(), 27 );
WGridRegular3D grid4( 3, 3, 3, WMatrix< double >( 4, 4 ) );
TS_ASSERT_EQUALS( grid4.size(), 27 );
}
/**
......@@ -137,6 +141,21 @@ public:
TS_ASSERT_DELTA( grid.getOffsetZ(), z.norm(), m_delta );
}
/**
* getDirection should return the vector direction prescribed by the use of
* the constructor
*/
void testGetDirection( void )
{
WVector3D x( 3., 1., 2. );
WVector3D y( 2., 6., 4. );
WVector3D z( 3., 6., 9. );
WGridRegular3D grid( 0., 0., 0., 10, 10, 10, x, y, z );
TS_ASSERT_EQUALS( grid.getDirectionX(), x );
TS_ASSERT_EQUALS( grid.getDirectionY(), y );
TS_ASSERT_EQUALS( grid.getDirectionZ(), z );
}
/**
* getOrigin should return the origin prescribed by the use of the constructor
* or (0,0,0) when using the second constructor.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment