ISIS Core Library 0.7.2 (api 3.0.0)

/scr/tee1/isis/lib/Core/DataStorage/common.cpp

Go to the documentation of this file.
00001 //
00002 // C++ Implementation: common (DataStorage)
00003 //
00004 // Description:
00005 //
00006 //
00007 // Author: Thomas Pröger <proeger@cbs.mpg.de>, (C) 2010
00008 //
00009 // Copyright: See COPYING file that comes with this distribution
00010 //
00011 //
00012 
00013 #include "common.hpp"
00014 #include "image.hpp"
00015 #include <boost/numeric/ublas/io.hpp>
00016 
00017 namespace isis
00018 {
00019 
00020 namespace data
00021 {
00022 
00023 namespace _internal
00024 {
00025 
00026 
00027 bool transformCoords( isis::util::PropertyMap &properties, util::vector4<size_t> size, boost::numeric::ublas::matrix<float> transform, bool transformCenterIsImageCenter  )
00028 {
00029     LOG_IF( !properties.hasProperty( "rowVec" ) || !properties.hasProperty( "columnVec" ) || !properties.hasProperty( "sliceVec" )
00030             || !properties.hasProperty( "voxelSize" ) || !properties.hasProperty( "indexOrigin" ), Debug, error )
00031             << "Missing one of the properties (rowVec, columnVec, sliceVec, voxelSize, indexOrigin)";
00032 
00033     using namespace boost::numeric::ublas;
00034     // this implementation assumes that the PropMap properties is either a
00035     // data::Chunk or a data::Image object. Hence it should contain the
00036     // properties rowVec, columnVec, sliceVec and indexOrigin.
00037     // get row, column and slice vector from property map
00038     isis::util::fvector3 row = properties.getPropertyAs<util::fvector3>( "rowVec" );
00039     isis::util::fvector3 column = properties.getPropertyAs<util::fvector3>( "columnVec" );
00040     isis::util::fvector3 slice = properties.getPropertyAs<util::fvector3>( "sliceVec" );
00041     // get index origin from property map
00042     isis::util::fvector3 indexorig = properties.getPropertyAs<util::fvector3>( "indexOrigin" );
00043     vector<float> origin_out = vector<float>( 3 );
00044     //check if we have a property "voxelGap" to prevent isis from throwing a warning "blabla"
00045     isis::util::fvector3 scaling;
00046 
00047     if( properties.hasProperty( "voxelGap" ) ) {
00048         scaling  = properties.getPropertyAs<util::fvector3>( "voxelSize" ) +  properties.getPropertyAs<util::fvector3>( "voxelGap" );
00049     } else {
00050         scaling  = properties.getPropertyAs<util::fvector3>( "voxelSize" );
00051     }
00052 
00053     // create boost::numeric data structures
00054     // STEP 1 transform orientation matrix
00055     // input matrix
00056     matrix<float> R_in( 3, 3 );
00057 
00058     for( int i = 0; i < 3; i++ ) {
00059         R_in( i, 0 ) = row[i];
00060         R_in( i, 1 ) = column[i];
00061         R_in( i, 2 ) = slice[i];
00062     }
00063 
00064     matrix<float> R_out( 3, 3 );
00065 
00066     if( transformCenterIsImageCenter ) {
00067         R_out = prod( R_in, transform );
00068     } else {
00069         R_out = prod( transform, R_in );
00070     }
00071 
00072     for ( int i = 0; i < 3; i++ ) {
00073         row[i] = R_out( i, 0 );
00074         column[i] = R_out( i, 1 );
00075         slice[i] = R_out( i, 2 );
00076     }
00077 
00078     vector<float> origin_in( 3 );
00079 
00080     for( int i = 0; i < 3; i++ ) {
00081         origin_in( i ) = indexorig[i];
00082     }
00083 
00084     //the center of the transformation is the image center (eg. spm transformation)
00085     if( transformCenterIsImageCenter ) {
00086         matrix<float> R_in_inverse( R_in );
00087 
00088         if( !_internal::inverseMatrix<float>( R_in, R_in_inverse ) ) {
00089             LOG( Runtime, error ) << "Can not inverse orientation matrix: " << R_in;
00090             return false;
00091         }
00092 
00093         //we have to map the indexes of the image size into the scanner space
00094 
00095         vector<float> physicalSize( 3 );
00096         vector<float> boostScaling( 3 );
00097 
00098         for ( unsigned short i = 0; i < 3; i++ ) {
00099             physicalSize( i ) = size[i] * scaling[i];
00100             boostScaling( i ) = scaling[i];
00101         }
00102 
00103         // now we have to calculate the center of the image in physical space
00104         vector<float> half_image( 3 );
00105 
00106         for ( unsigned short i = 0; i < 3; i++ ) {
00107             half_image( i ) = ( physicalSize( i )  - boostScaling( i ) ) * 0.5;
00108         }
00109 
00110         vector<float> center_image = prod( R_in, half_image ) + origin_in ;
00111         //now translate this center to the center of the physical space and get the new image origin
00112         vector<float> io_translated = origin_in - center_image;
00113         //now multiply this translated origin with the inverse of the orientation matrix of the image
00114         vector<float> io_ortho = prod( R_in_inverse, io_translated );
00115         //now transform this matrix with the actual transformation matrix
00116         vector<float> transformed_io_ortho = prod( io_ortho, transform );
00117         //now transform ths point back with the orientation matrix of the image
00118         vector<float> transformed_io = prod( R_in, transformed_io_ortho );
00119         //and finally we have to retranslate this origin to get the image to our old position in physical space
00120         origin_out = transformed_io + center_image;
00121 
00122     } else {
00123         origin_out = prod( transform, origin_in );
00124     }
00125 
00126     for( int i = 0; i < 3; i++ ) {
00127         indexorig[i] = origin_out( i );
00128     }
00129 
00130     // write modified values back into property map
00131     properties.setPropertyAs( "indexOrigin", indexorig );
00132     properties.setPropertyAs( "rowVec", row );
00133     properties.setPropertyAs( "columnVec", column );
00134     properties.setPropertyAs( "sliceVec", slice );
00135     return true;
00136 }
00137 
00138 }
00139 
00140 boost::filesystem::path getCommonSource( std::list<boost::filesystem::path> sources )
00141 {
00142     sources.erase( std::unique( sources.begin(), sources.end() ), sources.end() );
00143 
00144     if( sources.empty() ) {
00145         LOG( Runtime, error ) << "Failed to get common source";
00146         return boost::filesystem::path();
00147     } else if( sources.size() == 1 )
00148         return sources.front();
00149     else {
00150         BOOST_FOREACH( boost::filesystem::path & ref, sources )
00151         ref.remove_leaf();//@todo switch to ref.remove_filename() as soon as we drop support for boost < 1.44
00152         return getCommonSource( sources );
00153     }
00154 }
00155 boost::filesystem::path getCommonSource( const std::list<data::Image> &imgs )
00156 {
00157     std::list<boost::filesystem::path> sources;
00158     BOOST_FOREACH( const data::Image & img, imgs ) {
00159         if( img.hasProperty( "source" ) )
00160             sources.push_back( img.getPropertyAs<std::string>( "source" ) );
00161         else {
00162             BOOST_FOREACH( const util::PropertyValue & ref, img.getChunksProperties( "source", true ) ) {
00163                 sources.push_back( ref.as<std::string>() );
00164             }
00165         }
00166     }
00167     sources.sort();
00168     return getCommonSource( sources );
00169 }
00170 boost::filesystem::path getCommonSource( const data::Image &img )
00171 {
00172     return getCommonSource( std::list<data::Image>( 1, img ) );
00173 }
00174 
00175 }
00176 }