2 # ---------------------------------------------------------------------
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
10 # This software is governed by the CeCILL-B license under French law and
11 # abiding by the rules of distribution of free software. You can use,
12 # modify and/ or redistribute the software under the terms of the CeCILL-B
13 # license as circulated by CEA, CNRS and INRIA at the following URL
14 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15 # or in the file LICENSE.txt.
17 # As a counterpart to the access to the source code and rights to copy,
18 # modify and redistribute granted by the license, users are provided only
19 # with a limited warranty and the software's author, the holder of the
20 # economic rights, and the successive licensors have only limited
23 # The fact that you are presently reading this means that you have had
24 # knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------
28 // C++ Implementation: brukerimage
33 // Author: Denis Grenier, (C) 2009
35 // Copyright: See COPYING file that comes with this distribution
42 #include "brukerimage.h"
45 * @brief This method takes care of the initialization of the main parameters usually needed to deal with an MRI experiment
46 * @fn bool BrukerImage::Init(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
52 bool BrukerImage::Init(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
55 // on devrait plutot les nommer 'computeXXX' (setXXX est d'habitude réservé aux accesseurs 'publics')
57 setAbsoluteTimePosition (TheOrigAcqp,TheOrigReco,TheValue);
58 setRelativeTimePosition (TheOrigAcqp,TheOrigReco,TheValue);
59 setFOVpixels (TheOrigAcqp,TheOrigReco,TheValue);
60 setFOVcm (TheOrigAcqp,TheOrigReco,TheValue);
61 setSliceThickness (TheOrigAcqp,TheOrigReco,TheValue);
62 setTE (TheOrigAcqp,TheOrigReco,TheValue);
63 setTR (TheOrigAcqp,TheOrigReco,TheValue);
64 setTI (TheOrigAcqp,TheOrigReco,TheValue);
65 setFlipAngle (TheOrigAcqp,TheOrigReco,TheValue);
66 setLoopStamp (TheOrigAcqp,TheOrigReco,TheValue);
67 setNA (TheOrigAcqp,TheOrigReco,TheValue);
68 setNR (TheOrigAcqp,TheOrigReco,TheValue);
69 setNAE (TheOrigAcqp,TheOrigReco,TheValue);
70 setDS (TheOrigAcqp,TheOrigReco,TheValue);
71 setACQ_phase_factor (TheOrigAcqp,TheOrigReco,TheValue);
72 setRotationMatrixRPS2XYZ (TheOrigAcqp,TheOrigReco,TheValue);
73 setTranslationVectorRPS2XYZ (TheOrigAcqp,TheOrigReco,TheValue);
74 setWordType (TheOrigAcqp,TheOrigReco,TheValue);
75 setImageType (TheOrigAcqp,TheOrigReco,TheValue);
76 setDataEndianness (TheOrigAcqp,TheOrigReco,TheValue);
77 setImageByteSize (TheOrigAcqp,TheOrigReco,TheValue);
78 setBeginingOfImageInBytes (TheOrigAcqp,TheOrigReco,TheValue);
84 * @brief the constructor uses the BrukerDataSet's of the acqp and reco file
85 * @fn BrukerImage::BrukerImage(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco)
89 BrukerImage::BrukerImage(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco)
93 BrukerImage::~BrukerImage()
98 * @fn int BrukerImage::getAbsoluteTimePosition() const
99 * @brief AbsoluteTimePosition is an integer number giving the time of the begining of the acquisition of the dataset
100 * @return AbsoluteTimePosition int
102 int BrukerImage::getAbsoluteTimePosition() const
104 return AbsoluteTimePosition;
108 * @fn bool BrukerImage::setAbsoluteTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue )
109 * @brief AbsoluteTimePosition is an integer number giving the time of the begining of the acquisition of the dataset
115 bool BrukerImage::setAbsoluteTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue )
117 AbsoluteTimePosition = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_abs_time"].GetIntValue()[0];
122 * @brief RelativeTimePosition is the estimated time position of the time the k-space center was acquired
123 * This notion is very relative when dealing with long experiments and a line or object averaging (NA or NAE <> 1)
124 * @fn double BrukerImage::getRelativeTimePosition() const
127 double BrukerImage::getRelativeTimePosition() const
129 return RelativeTimePosition;
133 * @brief RelativeTimePosition is the estimated instant when the k-space center of each image was acquired
135 This notion is very relative when dealing with long experiments and a line or object averaging (NA or NAE <> 1)
136 * @fn bool BrukerImage::setRelativeTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue )
142 bool BrukerImage::setRelativeTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue )
144 long lTEMP = TheOrigAcqp.GetBrukerImageList()[TheValue].back();
145 RelativeTimePosition = TheOrigAcqp.ObjectVaryingProperties.getPositionTimePerNR(lTEMP);
150 * @brief FOVpixels is a 1x2 integer vector. it's one of the view value we need to pick in the reco headermap
151 * @fn bool BrukerImage::setFOVpixels(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
157 bool BrukerImage::setFOVpixels(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
159 FOVpixels = TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_size"].GetIntValue();
164 * @brief FOVpixels is a 1x2 integer vector. it's one of the view value we need to pick in the reco headermap
165 * @fn std::vector <int > BrukerImage::getFOVpixels() const
166 * @return std::vector <int >
168 const std::vector<int > &BrukerImage::getFOVpixels() const
174 * @brief FOVcm is also picked in reco headermap
175 * @fn bool BrukerImage::setFOVcm(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
181 bool BrukerImage::setFOVcm(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
183 FOVcm = TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_fov"].GetDoubleValue();
188 * @brief FOVcm is also picked in reco headermap
189 * @fn std::vector <double > BrukerImage::getFOVcm() const
190 * @return std::vector <double >
192 const std::vector <double > &BrukerImage::getFOVcm() const
198 * @brief SliceThickness is in milimeter
199 * @fn bool BrukerImage::setSliceThickness( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue)
205 bool BrukerImage::setSliceThickness( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue)
207 SliceThickness = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_slice_thick"].GetDoubleValue()[0];
212 * @brief SliceThickness is in milimeter
213 * @fn double BrukerImage::getSliceThickness() const
216 double BrukerImage::getSliceThickness() const
218 return SliceThickness;
222 * @brief picks the echo time of the image number TheValue
223 * @fn bool BrukerImage::setTE( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue)
229 bool BrukerImage::setTE( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue)
231 TE = TheOrigAcqp.ObjectVaryingProperties.getTE(TheOrigAcqp.GetBrukerImageList()[TheValue][0]);
236 * @fn double BrukerImage::getTE() const
237 * @brief picks the echo time of the image number TheValue
240 double BrukerImage::getTE() const
246 * @brief picks the repetition time of the image number TheValue
247 * @fn bool BrukerImage::setTR( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue)
253 bool BrukerImage::setTR(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
255 TR=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_repetition_time"].GetDoubleValue()[0];
260 * @fn double BrukerImage::getTR() const
261 * @brief picks the echo time of the image number TheValue
264 double BrukerImage::getTR() const
270 * @brief picks the invertion time of the image number TheValue
271 * @fn bool BrukerImage::setTI( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue)
277 bool BrukerImage::setTI(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
279 TI = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_inversion_time"].GetDoubleValue()[0];
284 * @fn double BrukerImage::getTI() const
285 * @brief picks the invertion time of the image number TheValue
288 double BrukerImage::getTI() const
294 * @brief picks the flip angle of the image number TheValue
295 * @fn bool BrukerImage::setFlipAngle( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue)
301 bool BrukerImage::setFlipAngle(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
303 FlipAngle = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_flip_angle"].GetIntValue()[0];
308 * @fn double BrukerImage::getFlipAngle() const
309 * @brief picks the flip angle of the image number TheValue
312 double BrukerImage::getFlipAngle() const
319 * @brief LoopStamp is a vector, copy of the values of all the loop for the image number TheValue
321 * The purpose of this "loopstamp" is to provide additionnal information if the methods provided by this class are not sufficient to singularize each image
322 * @fn bool BrukerImage::setLoopStamp(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
328 bool BrukerImage::setLoopStamp(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
330 LoopStamp = TheOrigAcqp.GetBrukerImageList()[TheValue];
335 * @brief LoopStamp is a vector, copy of the values of all the loop for the image number TheValue
336 * The purpose of this "loopstamp" is to provide additionnal information if the methods provided by this class are not sufficient to singularize each image
337 * @fn std::vector<int> BrukerImage::getLoopStamp() const
340 const std::vector<int> &BrukerImage::getLoopStamp() const
346 * @brief NA number of accumulation is useful to track image quality
347 * @fn bool BrukerImage::setNA(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
353 bool BrukerImage::setNA(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
355 NA=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "NA"].GetIntValue()[0];
360 * @brief NA number of accumulation is useful to track image quality
361 * @fn int BrukerImage::getNA() const
365 int BrukerImage::getNA() const
371 * @brief NAE number of object exterior accumulation is useful to track image quality and rather used than NA to average movement artefacts
372 * @fn bool BrukerImage::setNAE(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
378 bool BrukerImage::setNAE(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
380 NAE=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "NAE"].GetIntValue()[0];
385 * @brief NAE number of object exterior accumulation is useful to track image quality and rather used than NA to average movement artefacts
386 * @fn int BrukerImage::getNAE() const
390 int BrukerImage::getNAE() const
396 * @brief DS (dummy scan) is useful to establish a dynamic equilibrium or to know if one was used
397 * @fn bool BrukerImage::setDS(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
404 bool BrukerImage::setDS(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
406 DS=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "DS"].GetIntValue()[0];
411 @brief DS (dummy scan) is useful to establish a dynamic equilibrium or to know if one was used
412 @fn int BrukerImage::get() const
415 int BrukerImage::getDS() const
421 * @brief Phase factor is the number of kspace line acquired in a single shot
422 * @fn bool BrukerImage::setACQ_phase_factor(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
428 bool BrukerImage::setACQ_phase_factor(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
430 ACQ_phase_factor=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_phase_factor"].GetIntValue()[0];
435 * @brief Phase factor is the number of kspace line acquired in a single shot
436 * @fn int BrukerImage::getACQ_phase_factor() const
439 int BrukerImage::getACQ_phase_factor() const
441 return ACQ_phase_factor;
446 * @brief The number of repetition NR is used to repeat a full objects acquisition NR times with a given delay
447 * This method returns at which repetition belongs the image TheValue
448 * @fn bool BrukerImage::NR(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
454 bool BrukerImage::setNR(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
456 NR= TheOrigAcqp.GetBrukerImageList()[TheValue].back();
461 * @brief The number of repetition NR is used to repeat a full objects acquisition NR times with a given delay
462 * This method returns at which repetition belongs the image TheValue
463 * @fn int BrukerImage::getNR() const
466 int BrukerImage::getNR() const
472 * @brief RotationMatrixRPS2XYZ is a 3x3 rotation matrix giving the orientation of the TheValue image
473 * @fn bool BrukerImage::setRotationMatrixRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
479 bool BrukerImage::setRotationMatrixRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
481 RotationMatrixRPS2XYZ = TheOrigAcqp.ObjectVaryingProperties.getOrientation(TheOrigAcqp.GetBrukerImageList()[TheValue][2]);
486 @brief RotationMatrixRPS2XYZ is a 3x3 rotation matrix giving the orientation of the TheValue image
487 @fn std::vector<std::vector<double> > BrukerImage::getRotationMatrixRPS2XYZ() const
488 @return RotationMatrixRPS2XYZ
490 const std::vector<std::vector<double> > &BrukerImage::getRotationMatrixRPS2XYZ() const
492 return RotationMatrixRPS2XYZ;
496 * @brief TranslationVectorRPS2XYZ is a 1x3 vector of the TheValue image position to the magnet center (in mm)
497 * @fn bool BrukerImage::setTranslationVectorRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
503 bool BrukerImage::setTranslationVectorRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
505 TranslationVectorRPS2XYZ.clear();
506 TranslationVectorRPS2XYZ.push_back(TheOrigAcqp.ObjectVaryingProperties.getPositionR(TheOrigAcqp.GetBrukerImageList()[TheValue][2]));
507 TranslationVectorRPS2XYZ.push_back(TheOrigAcqp.ObjectVaryingProperties.getPositionP(TheOrigAcqp.GetBrukerImageList()[TheValue][2]));
508 TranslationVectorRPS2XYZ.push_back(TheOrigAcqp.ObjectVaryingProperties.getPositionS(TheOrigAcqp.GetBrukerImageList()[TheValue][2]));
513 @brief TranslationVectorRPS2XYZ is a 1x3 vector of the TheValue image position to the magnet center (in mm)
514 @fn std::vector<double> BrukerImage::getTranslationVectorRPS2XYZ() const
515 @return TranslationVectorRPS2XYZ
517 const std::vector<double> &BrukerImage::getTranslationVectorRPS2XYZ() const
519 return TranslationVectorRPS2XYZ;
523 * @brief WordType returns the type of data to read int32_t, int16_t, uint8_t or float32_t
524 * @fn bool BrukerImage::setWordType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
530 bool BrukerImage::setWordType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
532 WordType=TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_wordtype"].GetStringValue()[0];
537 @brief WordType returns the type of data to read int32_t, int16_t, uint8_t or float32_t
538 @fn std::string BrukerImage::getWordType() const
539 @return int32_t, int16_t, uint8_t or float32_t or UNKNOWN
541 std::string BrukerImage::getWordType() const
543 if(WordType == ((std::string) "_32BIT_SGN_INT")) return ((std::string)"int32_t");
544 if(WordType == ((std::string) "_16BIT_SGN_INT")) return ((std::string)"int16_t");
545 if(WordType == ((std::string) "_8BIT_UNSGN_INT")) return ((std::string)"uint8_t");
546 if(WordType == ((std::string) "_32BIT_FLOAT")) return ((std::string)"float32_t");
547 return ((std::string)"UNKNOWN");
551 * @brief ImageType returns the type of image : values real for amplitude, real imaginary or phase images and complex for complex images
552 * @fn bool BrukerImage::setImageType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
558 bool BrukerImage::setImageType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
560 ImageType=TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_image_type"].GetStringValue()[0];
565 @brief ImageType returns the type of image : values real for amplitude, real imaginary or phase images and complex for complex images
566 @fn std::string BrukerImage::getImageType() const
567 @return complex or real
569 std::string BrukerImage::getImageType() const
571 if(ImageType == ((std::string) "COMPLEXE_IMAGE")) return ((std::string)"complex");
572 return ((std::string)"real");
576 * @brief DataEndianness gives information on how to swap or no the binary data to read
577 * @fn bool BrukerImage::setDataEndianness(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
583 bool BrukerImage::setDataEndianness(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
585 DataEndianness=TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_byte_order"].GetStringValue()[0];
590 * @brief DataEndianness gives information on how to swap or no the binary data to read
591 * @fn std::string BrukerImage::getDataEndianness() const
592 * @return DataEndianness
594 const std::string &BrukerImage::getDataEndianness() const
596 return DataEndianness;
600 * @brief Information on the image size in byte, useful for offsets calculation
601 * @fn bool BrukerImage::setImageByteSize(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
607 bool BrukerImage::setImageByteSize(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
609 int Dimension, WordSize;
610 if (getImageType()==((std::string)"complex")) Dimension=2;
611 else if (getImageType()==((std::string)"real")) Dimension=1;
614 if (getWordType()==((std::string)"int32_t")||getWordType()==((std::string)"float32_t")) WordSize=4;
615 else if (getWordType()==((std::string)"int16_t")) WordSize=2;
616 else if (getWordType()==((std::string)"uint8_t")) WordSize=1;
617 else /*if (getWordType()==((std::string)"UNKNOWN"))*/ return false;
619 ImageByteSize = Dimension*WordSize*getFOVpixels()[0]*getFOVpixels()[1];
624 * @brief Information on the image size in byte, useful for offsets calculation
625 * @fn size_t BrukerImage::getImageByteSize() const
626 * @return ImageByteSize
628 size_t BrukerImage::getImageByteSize() const
630 return ImageByteSize;
634 * @brief BeginingOfImageInBytes is the offset of the image number TheValue to the begining of 2dseq file
635 * @fn size_t BrukerImage::getBeginingOfImageInBytes() const
636 * @return BeginingOfImageInBytes
638 size_t BrukerImage::getBeginingOfImageInBytes() const
640 return BeginingOfImageInBytes;
644 * @brief BeginingOfImageInBytes is the offset of the image number TheValue to the begining of 2dseq file
645 * @fn bool BrukerImage::setBeginingOfImageInBytes(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
651 bool BrukerImage::setBeginingOfImageInBytes (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue)
653 BeginingOfImageInBytes = TheValue*getImageByteSize();