]> Creatis software - creaBruker.git/blobdiff - lib/src1/bruker2dicom.cxx
Added CMake configuration to enable CDash tests.
[creaBruker.git] / lib / src1 / bruker2dicom.cxx
index e241166e05359b664b760a5c7a0d6b6ddb05c6a7..32cb9b29bb75041a6674d21063d7d330abfc6e6f 100644 (file)
@@ -1,3 +1,29 @@
+/*
+       # ---------------------------------------------------------------------
+       #
+       # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image 
+       #                        pour la Santé)
+       # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
+       # Previous Authors : Laurent Guigues, Jean-Pierre Roux
+       # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
+       #
+       #  This software is governed by the CeCILL-B license under French law and 
+       #  abiding by the rules of distribution of free software. You can  use, 
+       #  modify and/ or redistribute the software under the terms of the CeCILL-B 
+       #  license as circulated by CEA, CNRS and INRIA at the following URL 
+       #  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html 
+       #  or in the file LICENSE.txt.
+       #
+       #  As a counterpart to the access to the source code and  rights to copy,
+       #  modify and redistribute granted by the license, users are provided only
+       #  with a limited warranty  and the software's author,  the holder of the
+       #  economic rights,  and the successive licensors  have only  limited
+       #  liability. 
+       #
+       #  The fact that you are presently reading this means that you have had
+       #  knowledge of the CeCILL-B license and that you accept its terms.
+       # ------------------------------------------------------------------------
+*/
 #include "bruker2dicom.h"
 #include <boost/filesystem/path.hpp>
 #include <boost/filesystem/operations.hpp>
@@ -9,6 +35,7 @@
 
 bool Bruker2Dicom::Execute()
 {
+       int dimension = 1;
    // ----- Check input directory name -----
 
    bool bigEndian = GDCM_NAME_SPACE::Util::IsCurrentProcessorBigEndian();
@@ -83,7 +110,7 @@ bool Bruker2Dicom::Execute()
  
    switch (type)
    {
-      case 1: {   
+      case 1: {
          bool canOpen = br_subject.LoadFile(subject);
          if (!canOpen)
          {
@@ -99,7 +126,7 @@ bool Bruker2Dicom::Execute()
             subject_name = b_name.GetStringValue()[0];
             strPatientName = subject_name;
             cleanString(subject_name);
-            DealWithSingleStudyDirectory (fileNames);
+            DealWithSingleStudyDirectory (fileNames, dimension);
         }
          break;
       }
@@ -107,13 +134,13 @@ bool Bruker2Dicom::Execute()
       case 2: {
          subject_name = "defaultPatName";
         strPatientName = subject_name;
-         DealWithSingleStudyDirectory (fileNames);
+         DealWithSingleStudyDirectory (fileNames, dimension);
         break;
       }
 
       case 3: {
          std::cout << " User passed a 'non study' directory; Hope it's a *non recursive* 'set of studies' directory! (recursive not yet dealt with)" << std::endl;
-        DealWithMultiStudyDirectory (fileNames);
+        DealWithMultiStudyDirectory (fileNames, dimension);
         break;
       }
    }
@@ -121,7 +148,7 @@ bool Bruker2Dicom::Execute()
 
 // ----------------------------------------------------------------------------------------------------------
 
-void Bruker2Dicom::DealWithMultiStudyDirectory (GDCM_NAME_SPACE::DirListType &dirNames)
+void Bruker2Dicom::DealWithMultiStudyDirectory (GDCM_NAME_SPACE::DirListType &dirNames, int dimension)
 {
    GDCM_NAME_SPACE::DirListType::iterator it;
 
@@ -164,7 +191,7 @@ void Bruker2Dicom::DealWithMultiStudyDirectory (GDCM_NAME_SPACE::DirListType &di
             subject_name = b_name.GetStringValue()[0];
             strPatientName = subject_name;
             cleanString(subject_name);  
-            DealWithSingleStudyDirectory(fileNames);
+            DealWithSingleStudyDirectory(fileNames,dimension);
         }  
       }
       else
@@ -177,12 +204,14 @@ void Bruker2Dicom::DealWithMultiStudyDirectory (GDCM_NAME_SPACE::DirListType &di
 
 // ----------------------------------------------------------------------------------------------------------
 
-void Bruker2Dicom::DealWithSingleStudyDirectory (GDCM_NAME_SPACE::DirListType &fileNames)
+void Bruker2Dicom::DealWithSingleStudyDirectory (GDCM_NAME_SPACE::DirListType &fileNames, int dimension)
 {
      bool res;  
     // creation directory : 'nom du patient'
     std::string tempStringPatDir(OutputDirName);
-    tempStringPatDir = tempStringPatDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR + subject_name;
+
+    tempStringPatDir = tempStringPatDir + "/"+ subject_name;
+               //GDCM_NAME_SPACE::GDCM_FILESEPARATOR + subject_name; //FCY TO MODIFY
 
     res=CreateDirectory(tempStringPatDir);
     if (!res) {
@@ -221,7 +250,10 @@ void Bruker2Dicom::DealWithSingleStudyDirectory (GDCM_NAME_SPACE::DirListType &f
       subject_study_name = "defStudyName";         // Why not? 
    }
     // subject_name is already in 'Patient Name' 
-    strStudyDescr = /*subject_name + "." + */ subject_study_name + "." + subject_entry + "." + subject_position + "." + subject_date;
+    if (0) // We don't realy need so much information for 'Study'
+       strStudyDescr = /*subject_name + "." + */ subject_study_name + "." + subject_entry + "." + subject_position + "." + subject_date;
+    else
+       strStudyDescr = /*subject_name + "." + */ subject_study_name /*+ "." + subject_entry + "." + subject_position + "." + subject_date*/;
 
     // creation directory : 'nom de la Study'
 
@@ -316,7 +348,7 @@ void Bruker2Dicom::DealWithSingleStudyDirectory (GDCM_NAME_SPACE::DirListType &f
         if (verbose)
            printf ("outputDirName [%s]\n", outputDirName);
         try {
-           DealWithNiveau1(*it, strOutputDirName);
+           DealWithNiveau1(*it, strOutputDirName, dimension);
        }
        catch (BrukerHopelessException &e)
        {
@@ -329,7 +361,7 @@ void Bruker2Dicom::DealWithSingleStudyDirectory (GDCM_NAME_SPACE::DirListType &f
 
 // =====================================================================
 
-void Bruker2Dicom::DealWithNiveau1(std::string &level1Directory, std::string &currentOutputDirName) {
+void Bruker2Dicom::DealWithNiveau1(std::string &level1Directory, std::string &currentOutputDirName, int dimension) {
 //
 // e.g. : at level 1, in B67d1.Bp1/6
 //
@@ -431,7 +463,7 @@ void Bruker2Dicom::DealWithNiveau1(std::string &level1Directory, std::string &cu
           7 1  
   */
          try {
-            DealWithNiveau2(*it, strOutputDirName);
+            DealWithNiveau2(*it, strOutputDirName, dimension);
         }
         catch (BrukerHopelessException &e)
         {
@@ -444,7 +476,7 @@ void Bruker2Dicom::DealWithNiveau1(std::string &level1Directory, std::string &cu
 
 // =====================================================================
 
-void Bruker2Dicom::DealWithNiveau2(std::string &level2Directory, std::string &currentOutputDirName) {
+void Bruker2Dicom::DealWithNiveau2(std::string &level2Directory, std::string &currentOutputDirName, int dimension) {
 
 // e.g. : at level 2 in B67d1.Bp1/6/pdata
 //
@@ -488,32 +520,32 @@ void Bruker2Dicom::DealWithNiveau2(std::string &level2Directory, std::string &cu
        ++it)
    {
       if ( boost::filesystem::is_directory(*it) )
-      { 
-  
+      {
+
          if (verbose)
             std::cout << "--- --- [" << *it << "] is a directory" << std::endl;
 
-        // sprintf(outputDirName, "%s%c%s", currentOutputDirName.c_str(), 
+        // sprintf(outputDirName, "%s%c%s", currentOutputDirName.c_str(),
         //                          GDCM_NAME_SPACE::GDCM_FILESEPARATOR,
         //                                GDCM_NAME_SPACE::Util::GetName(*it).c_str() );
   // MUST be 'pdata'!
 
 //
 // (interest of previous method :
-// If unaware user changed the pdata name, it goes on working   
+// If unaware user changed the pdata name, it goes on working
 //
           std::string str_isa;
           str_isa = (*it) + 
                     GDCM_NAME_SPACE::GDCM_FILESEPARATOR +
                    "isa";
 
-          std::string str_isa_func_name;    
+          std::string str_isa_func_name;
           canOpen = br_isa.LoadFile(str_isa);
           if (!canOpen)
           {
              sprintf(outputDirName, "%s%c%s", currentOutputDirName.c_str(), 
                                           GDCM_NAME_SPACE::GDCM_FILESEPARATOR,
-                                          GDCM_NAME_SPACE::Util::GetName(*it).c_str() );        
+                                          GDCM_NAME_SPACE::Util::GetName(*it).c_str() );
           }
           else
           {
@@ -530,7 +562,7 @@ void Bruker2Dicom::DealWithNiveau2(std::string &level2Directory, std::string &cu
           }
          std::string strOutputDirName(outputDirName);
          try {
-             DealWithNiveau3(*it, strOutputDirName);
+             DealWithNiveau3(*it, strOutputDirName, dimension);
          }
          catch (BrukerHopelessException &e)
          {
@@ -543,7 +575,7 @@ void Bruker2Dicom::DealWithNiveau2(std::string &level2Directory, std::string &cu
             std::cout << "And Init Exception was thrown in DealWithNiveau3 (" << e.what() << "); " 
                       << " We skip [" << level2Directory << "]" << std::endl;
             continue;
-         }          
+         }
       }
    }
 }
@@ -552,7 +584,7 @@ void Bruker2Dicom::DealWithNiveau2(std::string &level2Directory, std::string &cu
 // =====================================================================
 //
 
-void Bruker2Dicom::DealWithNiveau3(std::string &level3Directory, std::string &currentOutputDirName){
+void Bruker2Dicom::DealWithNiveau3(std::string &level3Directory, std::string &currentOutputDirName, int dimension){
 
 //
 // e.g. at level 3, in
@@ -594,7 +626,7 @@ void Bruker2Dicom::DealWithNiveau3(std::string &level3Directory, std::string &cu
 
    if (verbose)
       std::cout << "d3proc: --- => [" << char_d3proc << "]" << std::endl;
-   std::string str_d3proc(char_d3proc);       
+   std::string str_d3proc(char_d3proc);     
    canOpen = br_d3proc.LoadFile(str_d3proc);
 
    if (!canOpen)
@@ -609,7 +641,7 @@ void Bruker2Dicom::DealWithNiveau3(std::string &level3Directory, std::string &cu
    {
       std::cout << "Hopeless! FillMap failed on 'd3proc'" << std::endl;
       throw ( BrukerHopelessException ("Hopeless! FillMap failed on 'd3proc'"));      
-      //exit(0);  /// \TODO throw an exception !     
+      //exit(0);  /// \TODO throw an exception !
    }
 
    //-------------- end try d3proc;
@@ -658,7 +690,7 @@ void Bruker2Dicom::DealWithNiveau3(std::string &level3Directory, std::string &cu
    } else {
       if (verbose)
          std::cout << "[" << str_reco << "] successfully Mapped" << std::endl;
-   }   
+   }
 
    //std::cout << "------------------------------------------------------------------------------------------------" << std::cout;
    // br_reco.PrintSelf();
@@ -717,20 +749,31 @@ void Bruker2Dicom::DealWithNiveau3(std::string &level3Directory, std::string &cu
 // Better we use 'get' accessors from BrukerImage class, as Denis wrote them
 
    BrukerFieldData fov = br_reco.GetFieldData("RECO_fov");
-   double fovX = fov.GetDoubleValue()[0];
-   double fovY = fov.GetDoubleValue()[1];
+
+   double fovX;
+   double fovY;
+   fovX= fov.GetDoubleValue()[0];
+   if(fov.GetDoubleValue().size() > 1)
+        fovY = fov.GetDoubleValue()[1];
    if (verbose)
       std::cout << "FOV (ds reco) " << fovX << " " << fovY << std::endl;
 
    BrukerFieldData size = br_reco.GetFieldData("RECO_size");
-   double sizeX = size.GetDoubleValue()[0];
-   double sizeY = size.GetDoubleValue()[1];
+   double sizeX;
+   double sizeY;
+   sizeX = size.GetDoubleValue()[0];
+   
+   if(fov.GetDoubleValue().size() > 1)
+    sizeY = size.GetDoubleValue()[1];
 
    if (verbose)
       std::cout << "SIZE (ds reco) " << sizeX << " " << sizeY << std::endl;
 
-   double spatResolX = fovX / sizeX;
-   double spatResolY = fovY / sizeY;
+   double spatResolX;
+   double spatResolY;
+   spatResolX = fovX / sizeX;
+    if(fov.GetDoubleValue().size() > 1)
+    spatResolY = fovY / sizeY;
 
    if (verbose)
       std::cout << "spatResol (ds reco : fov/size) " << spatResolX << " " << spatResolY << std::endl;
@@ -739,10 +782,12 @@ void Bruker2Dicom::DealWithNiveau3(std::string &level3Directory, std::string &cu
 
    /// \TODO probabely a more sophisticated accessor will be necessary :
    ///  (cf : non contiguous slices, overlapping, slice thickness, space between slices, etc)
-
+   double sliceDistance;
+   if(dimension > 1)
+   {
    BrukerFieldData bsliceDistance = br_method.GetFieldData("PVM_SPackArrSliceDistance");
-   double sliceDistance = bsliceDistance.GetDoubleValue()[0];
-
+    sliceDistance = bsliceDistance.GetDoubleValue()[0];
+   }
    if (verbose)
       std::cout << "SPackArrSliceDistance (ds method) " << sliceDistance << std::endl;   
 
@@ -770,6 +815,8 @@ void Bruker2Dicom::DealWithNiveau3(std::string &level3Directory, std::string &cu
    if (verbose)
          std::cout << "nbSlices " << nbSlices << std::endl;
    int k;
+   if(dimension ==1)
+          nbSlices = 1;
    int nbInstants = nbFrames/nbSlices;
    if (verbose)
          std::cout << "nbInstants (deduced)" << nbInstants << std::endl;    
@@ -807,7 +854,7 @@ void Bruker2Dicom::DealWithNiveau3(std::string &level3Directory, std::string &cu
    // This one will be important!
    // ---------------------------
    try {
-      imageSet = CreateImageSet ( );
+      imageSet = CreateImageSet ( dimension);
    }
    catch (BrukerInitException& e)
    {
@@ -1196,7 +1243,7 @@ void Bruker2Dicom::dealWithCarto(GDCM_NAME_SPACE::DirListType &fileNames, int NX
 int Bruker2Dicom::CheckUserDirectory(std::string &userDirName)
 {
    GDCM_NAME_SPACE::DirList dirList(userDirName, false, true); // DON'T get recursively the list of files
-     
+
    GDCM_NAME_SPACE::DirListType fileNames;
    fileNames = dirList.GetFilenames();
 
@@ -1219,7 +1266,7 @@ int Bruker2Dicom::CheckUserDirectory(std::string &userDirName)
        acqpFound= true; // user passes a 'serie', not a 'study' 
     else
        acqpFound = false; // user passed a 'non study' directory; Hope it's a 'set of studies' directory!
-   
+
    int type;    
    if  (subjectFound )  type = 1; // user passed a 'study
    else if  (acqpFound) type = 2; // user passed a 'serie' 
@@ -1281,10 +1328,10 @@ void Bruker2Dicom::cleanString(std::string &s)
       l--;
       s = s.substr(0, l);
    }   
-   
+
    if (s[0] == '<')      
       s= s.substr(1,l-2);
-   std::string repChar("_");   
+   std::string repChar("_");
    GDCM_NAME_SPACE::Util::ReplaceSpecChar(s, repChar);
 }
 
@@ -1358,18 +1405,18 @@ void Bruker2Dicom::getImhDataType(BrukerFieldData &bDPT, std::string &mhdDataPix
 
 // ===========================================================================================
 
-std::vector<BrukerImage> Bruker2Dicom::CreateImageSet ( )
+std::vector<BrukerImage> Bruker2Dicom::CreateImageSet ( int dimension)
 {
          std::vector<BrukerImage> imageSet;      
-         br_acqp.SetLoopStructure();
+         br_acqp.SetLoopStructure(dimension);
          std::vector<int> tempVect                      = br_acqp.GetLoopStructure() ;
          std::map<std::string, BrukerFieldData> map     = br_acqp.GetBrukerHeaderMap();
-        
+
          bool result                                    = br_acqp.ObjectVaryingProperties.init(map,tempVect);
 
          if (result == false)
         {
-           throw ( BrukerInitException  ("ObjectVaryingProperties.init() failure in Bruker2Dicom::CreateImageSet()") );
+           throw ( BrukerInitException ("ObjectVaryingProperties.init() failure in Bruker2Dicom::CreateImageSet()") );
         }
 
          br_acqp.SetImageLoopStructure();
@@ -1437,8 +1484,8 @@ void Bruker2Dicom::MakeDicomImage(unsigned char *tabPixels,
    std::ostringstream str;
 
    GDCM_NAME_SPACE::File *file;
-   file = GDCM_NAME_SPACE::File::New();       
-      
+   file = GDCM_NAME_SPACE::File::New();
+
   // Set the image size
    str.str(""); 
    str << X;
@@ -1457,7 +1504,9 @@ void Bruker2Dicom::MakeDicomImage(unsigned char *tabPixels,
   // Set the pixel type
   //      //8, 16, 32, 64 (for double ?)
    str.str("");
-   str << pixelSize*8;     
+   str << pixelSize*8;
+
+  // Bits Allocated
    file->InsertEntryString(str.str(),0x0028,0x0100,"US"); // Bits Allocated
 
    file->InsertEntryString(str.str(),0x0028,0x0101,"US"); // Bits Stored
@@ -1468,7 +1517,7 @@ void Bruker2Dicom::MakeDicomImage(unsigned char *tabPixels,
 
   // Set the pixel representation // 0/1 , 0=unsigned
    file->InsertEntryString("1",0x0028,0x0103, "US"); // Pixel Representation
-   
+
   // Set the samples per pixel // 1:Grey level, 3:RGB
    file->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
 
@@ -1476,25 +1525,25 @@ void Bruker2Dicom::MakeDicomImage(unsigned char *tabPixels,
    str.str("");
    str << spacingX << "\\" << spacingY;
    file->InsertEntryString(str.str(),0x0028,0x0030, "DS"); // Pixel Spacing     
-   
+
  //   0018 0050 DS 1 Slice Thickness 
    str.str("");    
    str << sliceDistance;
    file->InsertEntryString(str.str(),0x0018,0x0050, "DS"); 
-   
+
 //    0020 0011 IS 1 Series Number
    str.str("");    
    str << serieNumber;
    file->InsertEntryString(str.str(),0x0020,0x0011, "IS");
-      
+
 //    0020|0013 [IS]  [Instance Number] 
    instanceNumber++;
    str.str("");    
    str << instanceNumber;
    file->InsertEntryString(str.str(),0x0020,0x0013, "IS");
-     
+
   // 1.2.840.10008.5.1.4.1.1.4.1 : Enhanced MR Image Storage
- //  file->InsertEntryString("1.2.840.10008.5.1.4.1.1.4.1" , 0x0002, 0x0002, "UI");  // [Media Storage SOP Class UID]
 //  file->InsertEntryString("1.2.840.10008.5.1.4.1.1.4.1" , 0x0002, 0x0002, "UI");  // [Media Storage SOP Class UID]
   // file->InsertEntryString("1.2.840.10008.5.1.4.1.1.4.1" , 0x0008, 0x0016, "UI");  // [SOP Class UID]
 
 // OK : MR is NOT multiframe, but I want just a quick an dirty solution
@@ -1509,7 +1558,7 @@ void Bruker2Dicom::MakeDicomImage(unsigned char *tabPixels,
 
    file->InsertEntryString(studyUID, 0x0020, 0x000d, "UI");
    file->InsertEntryString(serieUID, 0x0020, 0x000e, "UI");
-   
+
 //  0008 0020 DA 1 Study Date
 //  0008 0030 TM 1 Study Time
 
@@ -1542,7 +1591,7 @@ std::cout << "charImageOrientation  " <<
                               imageSet[imgNum].getRotationMatrixRPS2XYZ()[1][0],
                               imageSet[imgNum].getRotationMatrixRPS2XYZ()[1][1],
                               imageSet[imgNum].getRotationMatrixRPS2XYZ()[1][2] ) ;
-    
+
    file->InsertEntryString(charImageOrientation,0x0020,0x0037, "DS");
 
 // 0020 0032 DS 3 Image Position (Patient) 
@@ -1552,9 +1601,95 @@ std::cout << "charImageOrientation  " <<
                              imageSet[imgNum].getTranslationVectorRPS2XYZ()[0], 
                              imageSet[imgNum].getTranslationVectorRPS2XYZ()[1],
                              imageSet[imgNum].getTranslationVectorRPS2XYZ()[2]);
-  
+
    file->InsertEntryString(charImagePosition,0x0020,0x0032, "DS");  //0020 0032 DS 3 Image Position (Patient) 
 
+   // Private creator
+   /*
+
+0029|0010 [LO]   [Private Creator] [CREATIS HEADER ]
+0029|0011 [LO]   [Private Creator] [CREATIS for BRUKER to DICOM]
+0029|1031 [LO]   [] [4.0.7571167 ]
+0029|1032 [UL]   [] [1440000] =0x(15f900)
+
+> $$ Thu Jul 30 17:29:46 2009 CEST (UT+2h)  mwiart
+> $$ /opt/PV4.0/data/mwiart/nmr/dha80.Uw1/4/method
+> ##$Method=DtiEpi
+> ##$PVM_DwNDiffDir=3             % 3 directions
+> ##$PVM_DwNDiffExpEach=2         % 2 valeurs de b par direction
+> ##$PVM_DwAoImages=1             % 1 image pour b=0
+> ##$PVM_DwBvalEach=( 2 )         % Valeurs de b
+> 1500.000000 3000.000000
+>
+> $$ Wed Dec  2 09:56:01 2009 UTC (UT+0h)  mwiart
+> $$ /opt/Pv5.0/data/mwiart/nmr/ECI7.Wx1/4/method
+> ##$Method=DtiEpi
+> ##$PVM_DwNDiffDir=3             % 3 directions
+> ##$PVM_DwNDiffExpEach=2         % 2 valeurs de b par direction
+> ##$PVM_DwAoImages=1             % 1 image pour b=0
+> ##$PVM_DwBvalEach=( 2 )         % Valeurs de b
+> 1500 3000
+>
+> $$ Wed Dec  2 10:14:27 2009 UTC (UT+0h)  mwiart
+> $$ /opt/Pv5.0/data/mwiart/nmr/ECI7.Wx1/5/method
+> ##$Method=DtiStandard
+> ##$PVM_DwNDiffDir=1             % 1 direction
+> ##$PVM_DwNDiffExpEach=2         % 2 valeurs de b
+> ##$PVM_DwAoImages=0             % 0 image pour b=0
+> ##$PVM_DwBvalEach=( 2 )         % Valeurs de b
+> 138 1600
+>
+   */
+
+   file->InsertEntryString("CREATIS HEADER", 0x0029,0x0010, "LO");
+   file->InsertEntryString("CREATIS FOR BRUKER-TO-DICOM", 0x0029,0x0011, "LO");
+
+   BrukerFieldData brf_method            = br_method.GetFieldData("Method");
+   const std::vector<std::string> method = brf_method.GetStringValue();
+
+  // std::string method = br_method.GetFieldData("Method").GetStringValue();    
+   file->InsertEntryString(method[0], 0x0029,0x0100, "LO");
+
+   std::cout << " method[" << method[0]  << "]" << std::endl;
+   if (method[0] == "DtiEpi" || method[0] == "DtiStandard")
+   {
+     // const std::vector<int> NDiffDir       = br_method.GetFieldData("PVM_DwNDiffDir").GetIntValue();
+      BrukerFieldData brf_NDiffDir    = br_method.GetFieldData("PVM_DwNDiffDir");
+      const std::vector<int> NDiffDir = brf_NDiffDir.GetIntValue();
+
+      //const std::vector<int> NDiffExpEach   = br_method.GetFieldData("PVM_DwNDiffExpEach").GetIntValue();
+      BrukerFieldData brf_NDiffExpEach      = br_method.GetFieldData("PVM_DwNDiffExpEach");
+      const std::vector<int> NDiffExpEach   =brf_NDiffExpEach.GetIntValue();
+
+//      const std::vector<int> AoImages     = br_method.GetFieldData("PVM_DwAoImages").GetIntValue();
+      BrukerFieldData brf_AoImages        = br_method.GetFieldData("PVM_DwAoImages");
+      const std::vector<int> AoImages     = brf_AoImages.GetIntValue();
+
+      BrukerFieldData brf_DwBvalEach       = br_method.GetFieldData("PVM_DwBvalEach");
+      const std::vector<double> DwBvalEach = brf_DwBvalEach.GetDoubleValue();
+
+ std::cout << "nb directions : " <<  NDiffDir[0] << " nb valeurs de b par direction : " << NDiffExpEach[0] 
+           << " nb images for b=0 : " << AoImages[0] << std::endl;
+
+       str.str(""); 
+       str << NDiffDir[0];
+       file->InsertEntryString(str.str(),0x0029,0x0101,"US"); // nb de directions
+       str.str(""); 
+       str << NDiffExpEach[0];
+       file->InsertEntryString(str.str(),0x0029,0x0102,"US"); // nb valeurs de b par direction       
+       str.str(""); 
+       str << AoImages[0];
+       file->InsertEntryString(str.str(),0x0029,0x0103,"US"); // nb images pour b=0
+
+       str.str("");
+       for (unsigned int i=0; i<NDiffExpEach[0]; i++) {
+          str << DwBvalEach[i];
+          if (i!=AoImages[0])
+             str << "\\";
+      }
+      file->InsertEntryString(str.str(),0x0029,0x0104,"DS"); // Valeurs de b
+   }   
+
 // 0020 0x1041 DS 1 Slice Location 
 //        sprintf(charImagePosition,"%f",float(imgNum));
 //        file->InsertEntryString(charImagePosition,0x0020,0x1041, "DS");   
@@ -1572,8 +1707,8 @@ std::cout << "charImageOrientation  " <<
 
    GDCM_NAME_SPACE::FileHelper *fileH;
    fileH = GDCM_NAME_SPACE::FileHelper::New(file);
-   fileH->SetContentType(contentType);   
-    
+   fileH->SetContentType(contentType);
+
    // cast is just to avoid warnings (*no* conversion is performed)
    //fileH->SetImageData((uint8_t *)img,int(maxX*maxY)*sizeof(uint16_t)); // troubles when maxX, mayY are *actually* float!