// // C++ Implementation: brukerimage // // Description: // // // Author: Denis Grenier, (C) 2009 // // Copyright: See COPYING file that comes with this distribution // // /** @file brukerimage.cpp */ #include "brukerimage.h" /** * This method takes care of the initialization of the main parameters usually needed to deal with an MRI experiment * @fn bool BrukerImage::Init(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::Init(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { // on devrait plutot les nommer 'computeXXX' (setXXX est d'habitude réservé aux accesseurs 'publics') setAbsoluteTimePosition (TheOrigAcqp,TheOrigReco,TheValue); setRelativeTimePosition (TheOrigAcqp,TheOrigReco,TheValue); setFOVpixels (TheOrigAcqp,TheOrigReco,TheValue); setFOVcm (TheOrigAcqp,TheOrigReco,TheValue); setSliceThickness (TheOrigAcqp,TheOrigReco,TheValue); setTE (TheOrigAcqp,TheOrigReco,TheValue); setTR (TheOrigAcqp,TheOrigReco,TheValue); setTI (TheOrigAcqp,TheOrigReco,TheValue); setFlipAngle (TheOrigAcqp,TheOrigReco,TheValue); setLoopStamp (TheOrigAcqp,TheOrigReco,TheValue); setNA (TheOrigAcqp,TheOrigReco,TheValue); setNR (TheOrigAcqp,TheOrigReco,TheValue); setNAE (TheOrigAcqp,TheOrigReco,TheValue); setDS (TheOrigAcqp,TheOrigReco,TheValue); setACQ_phase_factor (TheOrigAcqp,TheOrigReco,TheValue); setRotationMatrixRPS2XYZ (TheOrigAcqp,TheOrigReco,TheValue); setTranslationVectorRPS2XYZ (TheOrigAcqp,TheOrigReco,TheValue); setWordType (TheOrigAcqp,TheOrigReco,TheValue); setImageType (TheOrigAcqp,TheOrigReco,TheValue); setDataEndianness (TheOrigAcqp,TheOrigReco,TheValue); setImageByteSize (TheOrigAcqp,TheOrigReco,TheValue); setBeginingOfImageInBytes (TheOrigAcqp,TheOrigReco,TheValue); return true; } /** * @brief the constructor uses the BrukerDataSet's of the acqp and reco file * @fn BrukerImage::BrukerImage(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco) * @param TheOrigAcqp * @param TheOrigReco */ BrukerImage::BrukerImage(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco) { } BrukerImage::~BrukerImage() { } /** * @fn int BrukerImage::getAbsoluteTimePosition() const * @brief AbsoluteTimePosition is an integer number giving the time of the begining of the acquisition of the dataset * @return AbsoluteTimePosition int */ int BrukerImage::getAbsoluteTimePosition() const { return AbsoluteTimePosition; } /** * @fn bool BrukerImage::setAbsoluteTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue ) * @brief AbsoluteTimePosition is an integer number giving the time of the begining of the acquisition of the dataset * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setAbsoluteTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue ) { AbsoluteTimePosition = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_abs_time"].GetIntValue()[0]; return true; } /** * @brief RelativeTimePosition is the estimated time position of the time the k-space center was acquired * This notion is very relative when dealing with long experiments and a line or object averaging (NA or NAE <> 1) * @fn double BrukerImage::getRelativeTimePosition() const * @return double */ double BrukerImage::getRelativeTimePosition() const { return RelativeTimePosition; } /** * @brief RelativeTimePosition is the estimated instant when the k-space center of each image was acquired This notion is very relative when dealing with long experiments and a line or object averaging (NA or NAE <> 1) * @fn bool BrukerImage::setRelativeTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue ) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setRelativeTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue ) { long lTEMP = TheOrigAcqp.GetBrukerImageList()[TheValue].back(); RelativeTimePosition = TheOrigAcqp.ObjectVaryingProperties.getPositionTimePerNR(lTEMP); return true; } /** * @brief FOVpixels is a 1x2 integer vector. it's one of the view value we need to pick in the reco headermap * @fn bool BrukerImage::setFOVpixels(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setFOVpixels(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { FOVpixels = TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_size"].GetIntValue(); return true; } /** * @brief FOVpixels is a 1x2 integer vector. it's one of the view value we need to pick in the reco headermap * @fn std::vector BrukerImage::getFOVpixels() const * @return std::vector */ const std::vector &BrukerImage::getFOVpixels() const { return FOVpixels; } /** * @brief FOVcm is also picked in reco headermap * @fn bool BrukerImage::setFOVcm(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setFOVcm(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { FOVcm = TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_fov"].GetDoubleValue(); return true; } /** * @brief FOVcm is also picked in reco headermap * @fn std::vector BrukerImage::getFOVcm() const * @return std::vector */ const std::vector &BrukerImage::getFOVcm() const { return FOVcm; } /** * @brief SliceThickness is in milimeter * @fn bool BrukerImage::setSliceThickness( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setSliceThickness( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) { SliceThickness = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_slice_thick"].GetDoubleValue()[0]; return true; } /** * @brief SliceThickness is in milimeter * @fn double BrukerImage::getSliceThickness() const * @return double */ double BrukerImage::getSliceThickness() const { return SliceThickness; } /** * @brief picks the echo time of the image number TheValue * @fn bool BrukerImage::setTE( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setTE( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) { TE = TheOrigAcqp.ObjectVaryingProperties.getTE(TheOrigAcqp.GetBrukerImageList()[TheValue][0]); return true; } /** * @fn double BrukerImage::getTE() const * @brief picks the echo time of the image number TheValue * @return TE */ double BrukerImage::getTE() const { return TE; } /** * @brief picks the repetition time of the image number TheValue * @fn bool BrukerImage::setTR( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setTR(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { TR=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_repetition_time"].GetDoubleValue()[0]; return true; } /** * @fn double BrukerImage::getTR() const * @brief picks the echo time of the image number TheValue * @return TR */ double BrukerImage::getTR() const { return TR; } /** * @brief picks the invertion time of the image number TheValue * @fn bool BrukerImage::setTI( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setTI(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { TI = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_inversion_time"].GetDoubleValue()[0]; return true; } /** * @fn double BrukerImage::getTI() const * @brief picks the invertion time of the image number TheValue * @return TI */ double BrukerImage::getTI() const { return TI; } /** * @brief picks the flip angle of the image number TheValue * @fn bool BrukerImage::setFlipAngle( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setFlipAngle(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { FlipAngle = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_flip_angle"].GetIntValue()[0]; return true; } /** * @fn double BrukerImage::getFlipAngle() const * @brief picks the flip angle of the image number TheValue * @return FlipAngle */ double BrukerImage::getFlipAngle() const { return FlipAngle; } /** * @brief LoopStamp is a vector, copy of the values of all the loop for the image number TheValue * The purpose of this "loopstamp" is to provide additionnal information if the methods provided by this class are not sufficient to singularize each image * @fn bool BrukerImage::setLoopStamp(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setLoopStamp(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { LoopStamp = TheOrigAcqp.GetBrukerImageList()[TheValue]; return true; } /** * @brief LoopStamp is a vector, copy of the values of all the loop for the image number TheValue * The purpose of this "loopstamp" is to provide additionnal information if the methods provided by this class are not sufficient to singularize each image * @fn std::vector BrukerImage::getLoopStamp() const * @return LoopStamp */ const std::vector &BrukerImage::getLoopStamp() const { return LoopStamp; } /** * @brief NA number of accumulation is useful to track image quality * @fn bool BrukerImage::setNA(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return */ bool BrukerImage::setNA(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { NA=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "NA"].GetIntValue()[0]; return true; } /** * @brief NA number of accumulation is useful to track image quality * @fn int BrukerImage::getNA() const * * @return NA */ int BrukerImage::getNA() const { return NA; } /** @brief NAE number of object exterior accumulation is useful to track image quality and rather used than NA to average movement artefacts * @fn bool BrukerImage::setNAE(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setNAE(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { NAE=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "NAE"].GetIntValue()[0]; return true; } /** @brief NAE number of object exterior accumulation is useful to track image quality and rather used than NA to average movement artefacts * @fn int BrukerImage::getNAE() const * @return NAE */ int BrukerImage::getNAE() const { return NAE; } /** @brief DS (dummy scan) is useful to establish a dynamic equilibrium or to know if one was used * @fn bool BrukerImage::setDS(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setDS(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { DS=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "DS"].GetIntValue()[0]; return true; } /** @brief DS (dummy scan) is useful to establish a dynamic equilibrium or to know if one was used @fn int BrukerImage::get() const @return DS */ int BrukerImage::getDS() const { return DS; } /** @brief Phase factor is the number of kspace line acquired in a single shot * @fn bool BrukerImage::setACQ_phase_factor(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setACQ_phase_factor(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { ACQ_phase_factor=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_phase_factor"].GetIntValue()[0]; return true; } /** @brief Phase factor is the number of kspace line acquired in a single shot @fn int BrukerImage::getACQ_phase_factor() const @return */ int BrukerImage::getACQ_phase_factor() const { return ACQ_phase_factor; } /** @brief The number of repetition NR is used to repeat a full objects acquisition NR times with a given delay * This method returns at which repetition belongs the image TheValue * @fn bool BrukerImage::NR(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setNR(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { NR= TheOrigAcqp.GetBrukerImageList()[TheValue].back(); return true; } /** @brief The number of repetition NR is used to repeat a full objects acquisition NR times with a given delay * This method returns at which repetition belongs the image TheValue @fn int BrukerImage::getNR() const @return NR */ int BrukerImage::getNR() const { return NR; } /** @brief RotationMatrixRPS2XYZ is a 3x3 rotation matrix giving the orientation of the TheValue image * @fn bool BrukerImage::setRotationMatrixRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setRotationMatrixRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { RotationMatrixRPS2XYZ = TheOrigAcqp.ObjectVaryingProperties.getOrientation(TheOrigAcqp.GetBrukerImageList()[TheValue][2]); return true; } /** @brief RotationMatrixRPS2XYZ is a 3x3 rotation matrix giving the orientation of the TheValue image @fn std::vector > BrukerImage::getRotationMatrixRPS2XYZ() const @return RotationMatrixRPS2XYZ */ const std::vector > &BrukerImage::getRotationMatrixRPS2XYZ() const { return RotationMatrixRPS2XYZ; } /** @brief TranslationVectorRPS2XYZ is a 1x3 vector of the TheValue image position to the magnet center (in mm) * @fn bool BrukerImage::setTranslationVectorRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setTranslationVectorRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { TranslationVectorRPS2XYZ.clear(); TranslationVectorRPS2XYZ.push_back(TheOrigAcqp.ObjectVaryingProperties.getPositionR(TheOrigAcqp.GetBrukerImageList()[TheValue][2])); TranslationVectorRPS2XYZ.push_back(TheOrigAcqp.ObjectVaryingProperties.getPositionP(TheOrigAcqp.GetBrukerImageList()[TheValue][2])); TranslationVectorRPS2XYZ.push_back(TheOrigAcqp.ObjectVaryingProperties.getPositionS(TheOrigAcqp.GetBrukerImageList()[TheValue][2])); return true; } /** @brief TranslationVectorRPS2XYZ is a 1x3 vector of the TheValue image position to the magnet center (in mm) @fn std::vector BrukerImage::getTranslationVectorRPS2XYZ() const @return TranslationVectorRPS2XYZ */ const std::vector &BrukerImage::getTranslationVectorRPS2XYZ() const { return TranslationVectorRPS2XYZ; } /** @brief WordType returns the type of data to read int32_t, int16_t, uint8_t or float32_t * @fn bool BrukerImage::setWordType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setWordType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { WordType=TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_wordtype"].GetStringValue()[0]; return true; } /** @brief WordType returns the type of data to read int32_t, int16_t, uint8_t or float32_t @fn std::string BrukerImage::getWordType() const @return int32_t, int16_t, uint8_t or float32_t or UNKNOWN */ std::string BrukerImage::getWordType() const { if(WordType == ((std::string) "_32BIT_SGN_INT")) return ((std::string)"int32_t"); if(WordType == ((std::string) "_16BIT_SGN_INT")) return ((std::string)"int16_t"); if(WordType == ((std::string) "_8BIT_UNSGN_INT")) return ((std::string)"uint8_t"); if(WordType == ((std::string) "_32BIT_FLOAT")) return ((std::string)"float32_t"); return ((std::string)"UNKNOWN"); } /** @brief ImageType returns the type of image : values real for amplitude, real imaginary or phase images and complex for complex images * @fn bool BrukerImage::setImageType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setImageType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { ImageType=TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_image_type"].GetStringValue()[0]; return true; } /** @brief ImageType returns the type of image : values real for amplitude, real imaginary or phase images and complex for complex images @fn std::string BrukerImage::getImageType() const @return complex or real */ std::string BrukerImage::getImageType() const { if(ImageType == ((std::string) "COMPLEXE_IMAGE")) return ((std::string)"complex"); return ((std::string)"real"); } /** @brief DataEndianness gives information on how to swap or no the binary data to read * @fn bool BrukerImage::setDataEndianness(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setDataEndianness(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { DataEndianness=TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_byte_order"].GetStringValue()[0]; return true; } /** @brief DataEndianness gives information on how to swap or no the binary data to read @fn std::string BrukerImage::getDataEndianness() const @return DataEndianness */ const std::string &BrukerImage::getDataEndianness() const { return DataEndianness; } /** @brief Information on the image size in byte, useful for offsets calculation * @fn bool BrukerImage::setImageByteSize(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setImageByteSize(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { int Dimension, WordSize; if (getImageType()==((std::string)"complex")) Dimension=2; else if (getImageType()==((std::string)"real")) Dimension=1; else return false; if (getWordType()==((std::string)"int32_t")||getWordType()==((std::string)"float32_t")) WordSize=4; else if (getWordType()==((std::string)"int16_t")) WordSize=2; else if (getWordType()==((std::string)"uint8_t")) WordSize=1; else /*if (getWordType()==((std::string)"UNKNOWN"))*/ return false; ImageByteSize = Dimension*WordSize*getFOVpixels()[0]*getFOVpixels()[1]; return true; } /** @brief Information on the image size in byte, useful for offsets calculation @fn size_t BrukerImage::getImageByteSize() const @return ImageByteSize */ size_t BrukerImage::getImageByteSize() const { return ImageByteSize; } /** @brief BeginingOfImageInBytes is the offset of the image number TheValue to the begining of 2dseq file @fn size_t BrukerImage::getBeginingOfImageInBytes() const @return BeginingOfImageInBytes */ size_t BrukerImage::getBeginingOfImageInBytes() const { return BeginingOfImageInBytes; } /** @brief BeginingOfImageInBytes is the offset of the image number TheValue to the begining of 2dseq file * @fn bool BrukerImage::setBeginingOfImageInBytes(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) * @param TheOrigAcqp * @param TheOrigReco * @param TheValue * @return bool */ bool BrukerImage::setBeginingOfImageInBytes (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) { BeginingOfImageInBytes = TheValue*getImageByteSize(); return true; }