]> Creatis software - gdcm.git/blob - Example/ToInTag.cxx
In order to allow to use current version (1.3) of gdcm *and* ITK (that includes
[gdcm.git] / Example / ToInTag.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: ToInTag.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/05/23 14:18:04 $
7   Version:   $Revision: 1.11 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 #include "gdcmDocEntry.h"
19 #include "gdcmDicomDir.h"
20 #include "gdcmDicomDirPatient.h"
21 #include "gdcmFile.h"
22 #include "gdcmFileHelper.h"
23 #include "gdcmDirList.h"
24 #include "gdcmDebug.h"
25 #include "gdcmArgMgr.h"
26 #include "gdcmUtil.h"
27 #include "gdcmSerieHelper.h"
28
29 #include <iostream>
30
31 /**
32   * \brief   
33   *          - explores recursively the given directory
34   *          - keeps the requested series
35   *          - orders the gdcm-readable found Files
36   *            according to their Patient/Study/Serie/Image characteristics
37   *          - fills a single level Directory with *all* the files,
38   *            converted into a Brucker-like Dicom, Intags compliant
39   */  
40
41 typedef std::map<std::string, GDCM_NAME_SPACE::File*> SortedFiles;
42
43 int main(int argc, char *argv[]) 
44 {
45    START_USAGE(usage)
46    " \n ToInTag :\n                                                           ",
47    " - explores recursively the given directory,                              ",
48    " - keeps the requested series/ drops the unrequested series               ",
49    " - orders the gdcm-readable found Files according to their                ",
50    "           (0x0010, 0x0010) Patient's Name                                ",
51    "           (0x0020, 0x000e) Series Instance UID                           ",
52    "           (0x0020, 0x0032) Image Position (Patient)                      ",
53    "           (0x0018, 0x1060) Trigger Time                                  ",
54    "           (0x0018, 0x1312) In-plane Phase Encoding Direction             ",
55    " - fills a single level (*) Directory with *all* the files,               ",
56    "           converted into a Brucker-like Dicom, InTags compliant          ",
57    "   (*) actually : creates as many directories as Patients                 ",
58    "                  -that shouldn't appear, but being carefull is better ! -",
59    " or                                                                       ",
60    " - fills a tree-like structure of directories as :                        ",
61    "        - Patient                                                         ",
62    "        -- Serie                                                          ",
63    "        --- Position                                                      ",
64    "            Images are (sorted by Trigger Time /                          ",
65    "                     Encoding Direction (Row, Column)                     ",
66    "      use :                                                               ",
67    "           0x0021, 0x1020 : 'SLICE INDEX'                                 ",
68    "           0x0021, 0x1040 : 'FRAME INDEX'                                 ",
69    "           0x0020, 0x0012 : 'SESSION INDEX'  (Acquisition Number)         ",
70    " usage:                                                                   ",
71    " ToInTag          dirin=rootDirectoryName                                 ",
72    "                  dirout=outputDirectoryName                              ",
73    "                  {  [keep= list of seriesNumber to process]              ",
74    "                   | [drop= list of seriesNumber to ignore] }             ",
75    "                  [taggrid] [skel]                                        ",
76    "                  [input = {ACR|DCM}]                                     ", 
77    "                  [extent=image suffix (.IMA, .NEMA, .DCM, ...)]          ",
78    "                  [listonly] [split]                                      ",
79    "                  [noshadowseq][noshadow][noseq] [verbose] [debug]        ",
80    "                                                                          ",
81    " dirout : will be created if doesn't exist                                ",
82    " keep : if user wants to process a limited number of series               ",
83    "            he gives the list of 'SeriesNumber' (tag 0020|0011)           ",
84    " drop : if user wants to ignore a limited number of series                ",
85    "            he gives the list of 'SeriesNumber' (tag 0020|0011)           ",   
86    "        SeriesNumber are short enough to be human readable                ",
87    "        e.g : 1030,1035,1043                                              ", 
88    " taggrid : user knows all the images are 'grid' -ie : not 'col', not 'raw'",
89    " extent : DO NOT forget the leading '.' !                                 ",
90    " skel: name skeleton eg : patName_1.nema -> skel=patName_                 ",
91    " split: creates a tree-like structure of directories as :                 ",
92    "        - Patient                                                         ",
93    "        -- Serie                                                          ",
94    "        --- Position                                                      ",
95    "            Images are (sorted by Trigger Time /                          ",
96    "                     Encoding Direction (Row, Column)                     ",
97    " noshadowseq: user doesn't want to load Private Sequences                 ",
98    " noshadow : user doesn't want to load Private groups (odd number)         ",
99    " noseq    : user doesn't want to load Sequences                           ",
100    " verbose  : user wants to run the program in 'verbose mode'               ",
101    " debug    : *developer*  wants to run the program in 'debug mode'         ",
102    FINISH_USAGE
103
104    std::cout << "inside ToInTag" << std::endl;
105    
106    // ----- Initialize Arguments Manager ------
107       
108    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
109   
110    if (argc == 1 || am->ArgMgrDefined("usage")) 
111    {
112       am->ArgMgrUsage(usage); // Display 'usage'
113       delete am;
114       return 0;
115    }
116
117    const char *dirNamein;   
118    dirNamein  = am->ArgMgrGetString("dirin","."); 
119
120    const char *dirNameout;   
121    dirNameout  = am->ArgMgrGetString("dirout",".");  
122    
123    int loadMode = GDCM_NAME_SPACE::LD_ALL;
124    if ( am->ArgMgrDefined("noshadowseq") )
125       loadMode |= GDCM_NAME_SPACE::LD_NOSHADOWSEQ;
126    else 
127    {
128    if ( am->ArgMgrDefined("noshadow") )
129          loadMode |= GDCM_NAME_SPACE::LD_NOSHADOW;
130       if ( am->ArgMgrDefined("noseq") )
131          loadMode |= GDCM_NAME_SPACE::LD_NOSEQ;
132    }
133
134    if (am->ArgMgrDefined("debug"))
135       GDCM_NAME_SPACE::Debug::DebugOn();
136       
137    int verbose  = am->ArgMgrDefined("verbose");
138    int split    = am->ArgMgrDefined("split");
139    int listonly = am->ArgMgrDefined("listonly");
140          
141    int nbSeriesToKeep;
142    int *seriesToKeep = am->ArgMgrGetListOfInt("keep", &nbSeriesToKeep);
143    int nbSeriesToDrop;
144    int *seriesToDrop = am->ArgMgrGetListOfInt("drop", &nbSeriesToDrop);
145  
146    if ( nbSeriesToKeep!=0 && nbSeriesToDrop!=0)
147    {
148       std::cout << "KEEP and DROP are mutually exclusive !" << std::endl;
149       delete am;
150       return 0;         
151    }
152    
153    int taggrid = am->ArgMgrDefined("taggrid");
154    
155    int hasSkel = am->ArgMgrDefined("skel");
156    const char *skel;
157    if (hasSkel)
158       skel = am->ArgMgrGetString("skel");   
159       
160    const char *extent  = am->ArgMgrGetString("extent",".DCM");
161    
162    // if unused Param we give up
163    if ( am->ArgMgrPrintUnusedLabels() )
164    { 
165       am->ArgMgrUsage(usage);
166       delete am;
167       return 0;
168    }
169    delete am;  // we don't need Argument Manager any longer
170
171    // ----- Begin Processing -----
172    
173    if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNamein) )
174    {
175       std::cout << "KO : [" << dirNamein << "] is not a Directory." << std::endl;
176       return 0;
177
178    }
179    else
180    {
181       std::cout << "OK : [" << dirNamein << "] is a Directory." << std::endl;
182    }
183
184    std::string systemCommand;
185    
186    std::cout << "Check for output directory :[" << dirNameout << "]."
187              <<std::endl;
188    if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) )    // dirout not found
189    {
190       std::string strDirNameout(dirNameout);          // to please gcc 4
191       systemCommand = "mkdir " +strDirNameout;        // create it!
192       if (verbose)
193          std::cout << systemCommand << std::endl;
194       system (systemCommand.c_str());
195       if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // be sure it worked
196       {
197           std::cout << "KO : not a dir : [" << dirNameout << "] (creation failure ?)" << std::endl;
198       return 0;
199
200       }
201       else
202       {
203         std::cout << "Directory [" << dirNameout << "] created." << std::endl;
204       }
205    }
206    else
207    {
208        std::cout << "Output Directory [" << dirNameout << "] already exists; Used as is." << std::endl;
209    }
210     
211    std::string strDirNamein(dirNamein);
212    GDCM_NAME_SPACE::DirList dirList(strDirNamein, true); // get recursively the list of files
213    
214    if (listonly)
215    {
216       std::cout << "------------List of found files ------------" << std::endl;
217       dirList.Print();
218       std::cout << std::endl;
219    }
220    
221    GDCM_NAME_SPACE::DirListType fileNames;
222    fileNames = dirList.GetFilenames();
223    GDCM_NAME_SPACE::SerieHelper *s;              // Needed only to may use SerieHelper::AddSeriesDetail()
224    s = GDCM_NAME_SPACE::SerieHelper::New();
225
226    std::string token = "%%%"; // Hope it's enough!
227 /*       
228    std::cout << "---------------Print Serie--------------" << std::endl; 
229    s->SetDirectory(dirNamein, true); // true : recursive exploration 
230    s->SetUseSeriesDetails(true);  
231    s->AddSeriesDetail(0x0018, 0x1312);   
232    s->Print();
233 */
234   
235    GDCM_NAME_SPACE::File *f;
236    GDCM_NAME_SPACE::FileHelper *fh;
237    std::vector<std::string> tokens;
238    std::vector<std::string> tokensForFileName;
239    
240    // For Siemens pb, we need Station Name
241    
242    GDCM_NAME_SPACE::DirListType::iterator it1 = fileNames.begin();
243    f = GDCM_NAME_SPACE::File::New();
244    f->SetLoadMode(GDCM_NAME_SPACE::LD_ALL);
245    f->SetFileName( *it1 );
246    f->Load();
247    std::string stationName = f->GetEntryString(0x0008,0x1010);
248    f->Delete();   
249    
250 /*   
251    std::cout << "---------------Print Unique Series identifiers---------"  
252              << std::endl;     
253    std::string uniqueSeriesIdentifier;
254  
255    for (GDCM_NAME_SPACE::DirListType::iterator it) = fileNames.begin();  
256                                     it != fileNames.end();
257                                   ++it)
258    {
259       std::cout << "File Name : " << *it << std::endl;
260       f = GDCM_NAME_SPACE::File::New();
261       f->SetLoadMode(GDCM_NAME_SPACE::LD_ALL);
262       f->SetFileName( *it );
263       f->Load();
264         
265       uniqueSeriesIdentifier=s->CreateUniqueSeriesIdentifier(f);
266       std::cout << "                           [" <<
267                uniqueSeriesIdentifier  << "]" << std::endl;       
268       f->Delete();
269    }
270 */
271    
272    if (verbose)
273       std::cout << "------------------Print Break levels-----------------" << std::endl;
274
275    std::string userFileIdentifier; 
276    SortedFiles sf;
277
278    s->AddSeriesDetail(0x0010, 0x0010, false); // Patient's Name
279    if ( stationName != "MRC35150" ) // for Siemens MRC35150, don't deal with 'Series Instance UID'
280       s->AddSeriesDetail(0x0020, 0x000e, false); // Series Instance UID
281    else
282       s->AddSeriesDetail(0x9999, 0x9999, false); // dirty trick to ignore 'Series Instance UID'
283    s->AddSeriesDetail(0x0020, 0x0032, false); // Image Position (Patient)     
284    s->AddSeriesDetail(0x0018, 0x1060, true);  // Trigger Time (true: convert to keep numerical order)
285    s->AddSeriesDetail(0x0018, 0x1312, false); // In-plane Phase Encoding Direction 
286    s->AddSeriesDetail(0x0008, 0x103e, false); // Series Description (special Siemens ...)  
287
288    //uint8_t *imageData; // Useless : pixels will not be loaded 
289                          //          (images are overwritten)
290          
291    for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin();  
292                                     it != fileNames.end();
293                                   ++it)
294    {
295       f = GDCM_NAME_SPACE::File::New();
296       f->SetLoadMode(loadMode);
297       f->SetFileName( *it );
298       f->Load();
299
300       std::string strSeriesNumber;
301       int seriesNumber;
302       int j;
303
304       // keep only requested Series      
305       bool keep = false;
306       if (nbSeriesToKeep != 0)
307       {     
308          strSeriesNumber = f->GetEntryString(0x0020, 0x0011 );
309          seriesNumber = atoi( strSeriesNumber.c_str() );
310          for (j=0;j<nbSeriesToKeep; j++)
311          {
312             if(seriesNumber == seriesToKeep[j])
313             {
314                keep = true;
315                break;
316             }
317          }
318          if ( !keep)
319          {
320             f->Delete();
321             continue;
322          } 
323       }
324       // drop all unrequested Series
325       bool drop = false;
326       if (nbSeriesToDrop != 0)
327       {     
328          strSeriesNumber = f->GetEntryString(0x0020, 0x0011 );
329          seriesNumber = atoi( strSeriesNumber.c_str() );
330          for (j=0;j<nbSeriesToDrop; j++)
331          {
332             if(seriesNumber == seriesToDrop[j])
333             { 
334                drop = true;
335                break;
336             }
337         }
338         if (drop)
339         {
340            f->Delete();
341            continue;
342         }
343       }      
344
345       userFileIdentifier=s->CreateUserDefinedFileIdentifier(f); 
346       tokens.clear();
347       GDCM_NAME_SPACE::Util::Tokenize (userFileIdentifier, tokens, token); 
348    
349       int imageNum; // Within FileName
350       char newName[1024];
351       
352       if ( tokens[3] == "gdcmUnfound")  // sometimes Trigger Time is not found. CreateUserDefinedFileIdentifier is not aware of the pb.
353       {
354          ///this is a trick to build up a lexicographical compliant name :
355          ///     eg : fich001.ima vs fich100.ima as opposed to fich1.ima vs fich100.ima
356          std::string name = GDCM_NAME_SPACE::Util::GetName( *it );
357          if (hasSkel)
358          {
359             GDCM_NAME_SPACE::Util::Tokenize (name, tokensForFileName, skel);
360             imageNum = atoi ( tokensForFileName[0].c_str() );
361             // probabely we could write something much more complicated using C++ !
362             sprintf (newName, "%s%06d%s", skel, imageNum, extent);
363             tokens[3] = newName;
364             tokensForFileName.clear();    
365          }
366          else
367             tokens[3] = name;
368  
369  
370          userFileIdentifier = tokens[0] + token + tokens[1] + token + tokens[2] + token 
371                     + tokens[3] + token + tokens[4] + token + tokens[5] + token;
372       }   
373       if (verbose) 
374          std::cout << "[" << userFileIdentifier  << "] : " << *it << std::endl;
375                
376       // storing in a map ensures automatic sorting !      
377       sf[userFileIdentifier] = f;
378    }
379    
380    if (verbose)
381       std::cout << "  " << std::endl;
382       
383    std::string fullFilename, lastFilename;
384    std::string previousPatientName, currentPatientName;
385    std::string previousSerieInstanceUID, currentSerieInstanceUID;
386    std::string previousImagePosition, currentImagePosition;
387    std::string previousPhaseEncodingDirection, currentPhaseEncodingDirection;
388    std::string previousTriggerTime, currentTriggerTime;
389    
390    std::string currentStudyUID;
391    std::string seriesDescription;  
392       
393    std::string writeDir, currentWriteDir;
394    std::string currentPatientWriteDir, currentSerieWriteDir, 
395                currentPositionWriteDir, currentPhaseEncodingDirectionWriteDir;
396
397    std::string fullWriteFilename;
398    std::string strExtent(extent); 
399            
400    writeDir = GDCM_NAME_SPACE::Util::NormalizePath(dirNameout);     
401    SortedFiles::iterator it2;
402  
403    previousPatientName            = "";
404    previousSerieInstanceUID       = "";   
405    previousImagePosition          = "";
406    previousPhaseEncodingDirection = "";
407    previousTriggerTime            = "";
408    
409    int sliceIndex = 0; // Is incremented *at the beginning* of processing
410    int frameIndex;
411    if (taggrid)
412        frameIndex = 0;
413    else
414        frameIndex = 1;
415               
416    int flag       = 0;
417        
418    GDCM_NAME_SPACE::File *currentFile;
419
420    std::string defaultStudyUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
421    std::string defaultSerieUID;
422      
423    for (it2 = sf.begin() ; it2 != sf.end(); ++it2)
424    {  
425       currentFile = it2->second;
426        
427       fullFilename =  currentFile->GetFileName();
428       lastFilename =  GDCM_NAME_SPACE::Util::GetName( fullFilename ); 
429       std::cout << " --------------------------------------------------"
430                 << " Rewrite [" <<lastFilename << "]" << std::endl;
431      
432       tokens.clear();
433       GDCM_NAME_SPACE::Util::Tokenize (it2->first, tokens, token);
434       
435       currentPatientName            = tokens[0];
436       currentSerieInstanceUID       = tokens[1];
437       currentImagePosition          = tokens[2];
438       currentTriggerTime            = tokens[3];
439       currentPhaseEncodingDirection = tokens[4];
440       seriesDescription             = tokens[5];  // For Siemens pb
441
442       if ( currentImagePosition[0] == '-')
443           currentImagePosition[0] = 'M';
444       if ( currentImagePosition[0] == '+')
445           currentImagePosition[0] = 'P'; 
446
447       // Add a default ImagePositionPatient to avoid confusion at post processing time
448       if ( currentFile->GetEntryString(0x0020,0x0032) == GDCM_NAME_SPACE::GDCM_UNFOUND && 
449            currentFile->GetEntryString(0x0020,0x0030) == GDCM_NAME_SPACE::GDCM_UNFOUND )
450       {
451          currentFile->InsertEntryString("0.\\0.\\0.",0x0020, 0x0032, "DS" );
452       }
453
454       // Add a default ImagePositionPatient to avoid confusion at post processing time
455       if ( currentFile->GetEntryString(0x0020,0x0037) == GDCM_NAME_SPACE::GDCM_UNFOUND && 
456            currentFile->GetEntryString(0x0020,0x0035) == GDCM_NAME_SPACE::GDCM_UNFOUND )
457       {
458          currentFile->InsertEntryString("1.\\0.\\0.\\0.\\1.\\0.",0x0020, 0x0037, "DS" );
459       }
460       
461       if (previousPatientName != currentPatientName)
462       {      
463          if ( currentFile->GetEntryString(0x0020,0x000d) == GDCM_NAME_SPACE::GDCM_UNFOUND)
464          {
465             if (verbose)   
466                std::cout << "--- new  Study UID created" << std::endl;
467             defaultStudyUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
468             currentFile->InsertEntryString(defaultStudyUID, 0x0020, 0x000d, "UI" );
469          }
470   
471          previousPatientName = currentPatientName;
472          if (verbose)   
473             std::cout << "==== new Patient  [" << currentPatientName  << "]" << std::endl;
474     
475          previousPatientName            = currentPatientName;
476          previousSerieInstanceUID       = ""; //currentSerieInstanceUID;
477          previousImagePosition          = ""; //currentImagePosition;
478          previousTriggerTime            = "";
479          previousPhaseEncodingDirection = ""; //currentPhaseEncodingDirection;
480   
481          currentPatientWriteDir = writeDir + currentPatientName;
482          //if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(currentPatientWriteDir) )
483            {
484               systemCommand   = "mkdir " + currentPatientWriteDir;
485               if (verbose)
486                  std::cout << systemCommand << std::endl;
487               system ( systemCommand.c_str() );
488          }
489       }
490
491       if ( stationName != "MRC35150" ) // for Siemens MRC35150, don't deal with 'Series Instance UID'
492
493       if (previousSerieInstanceUID != currentSerieInstanceUID)
494       {        
495          if (verbose)   
496             std::cout << "==== === new Serie [" << currentSerieInstanceUID << "]"
497                       << std::endl;
498       
499          if ( currentFile->GetEntryString(0x0020,0x000e) == GDCM_NAME_SPACE::GDCM_UNFOUND)
500          {
501             if (verbose)   
502                std::cout << "--- --- new  Serie UID created" << std::endl;
503             defaultSerieUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
504             currentFile->InsertEntryString(defaultSerieUID, 0x0020, 0x000e, "UI" );
505          }       
506       
507          if (split)
508          {
509              currentSerieWriteDir  = currentPatientWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR
510                              + currentSerieInstanceUID;
511              systemCommand   = "mkdir " + currentSerieWriteDir;  
512              system (systemCommand.c_str());
513          }
514          previousSerieInstanceUID       = currentSerieInstanceUID;
515          previousImagePosition          = ""; //currentImagePosition;
516          previousPhaseEncodingDirection = ""; //currentPhaseEncodingDirection;
517       }
518       // end of stationName != "MRC35150"
519       
520       if (previousImagePosition != currentImagePosition)
521       {
522          frameIndex = 1;
523          flag = 0;        
524          if (verbose)   
525             std::cout << "=== === === new Position [" << currentImagePosition  << "]"
526                       << std::endl;
527          if (split)
528          {
529              currentPositionWriteDir  = currentSerieWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR
530                              + currentImagePosition;
531              systemCommand   = "mkdir " + currentPositionWriteDir;     
532              system (systemCommand.c_str()); 
533          }
534          previousImagePosition          = currentImagePosition;
535          previousPhaseEncodingDirection = ""; //currentPhaseEncodingDirection;
536          if (split)
537             sliceIndex = 1; // only *one* slice in a given directory
538          else
539             sliceIndex += 1;
540       }
541       if (verbose)
542          std::cout << "Slice Index : " << sliceIndex << std::endl;      
543
544 // We don't split on Row/Column!
545 /*
546       if (previousPhaseEncodingDirection != currentPhaseEncodingDirection)
547       {        
548          if (verbose)   
549             std::cout << "==== === === === new PhaseEncodingDirection [" 
550                       << currentPhaseEncodingDirection  << "]" << std::endl;
551       
552          if (split)
553          {
554              currentPhaseEncodingDirectionWriteDir  = currentPositionWriteDir 
555                              + GDCM_NAME_SPACE::GDCM_FILESEPARATOR
556                              + currentPhaseEncodingDirection;
557              systemCommand   = "mkdir " + currentPhaseEncodingDirectionWriteDir;     
558              system (systemCommand.c_str());     
559          }      
560     
561          previousPhaseEncodingDirection = currentPhaseEncodingDirection;
562       } 
563 */    
564       
565       if (verbose)
566          std::cout << "--- --- --- --- --- " << (it2->second)->GetFileName() 
567                    << std::endl;
568    
569       if ( GDCM_NAME_SPACE::Debug::GetDebugFlag())
570          std::cout << "--- --- --- --- --- " << it2->first << "  " 
571                    << (it2->second)->GetFileName() << " " 
572                    << GDCM_NAME_SPACE::Util::GetName( fullFilename ) << std::endl;           
573       
574       // Transform the image to be 'Brucker-Like'
575       // ----------------------------------------   
576     
577       // Deal with 0x0019, 0x1000 : 'FOV'
578       int nX = currentFile->GetXSize();
579       int nY = currentFile->GetYSize();
580       float pxSzX = currentFile->GetXSpacing();
581       float pxSzY = currentFile->GetYSpacing();
582       char fov[64];
583       sprintf(fov, "%f\\%f",nX*pxSzX, nY*pxSzY);
584       if (currentFile->IsVRCoherent(0x0019) == 1 )
585          currentFile->InsertEntryString(fov, 0x0019, 0x1000, "  ");
586       else     
587          currentFile->InsertEntryString(fov, 0x0019, 0x1000, "DS");
588
589      
590       // Deal with 0x0020, 0x0012 : 'SESSION INDEX'  (Acquisition Number)
591       std::string chSessionIndex;
592       // CLEANME
593
594
595       if (taggrid)
596       { 
597          chSessionIndex = "1";
598       }
599       else
600       {
601       /* for SIEMENS MRI :
602         D 0008|1010 [SH]  [Station Name ] [MRC35150]
603         we have to deal with :
604      
605         D 0008|103e [LO]  [Series Description ] [fl2d9_line PA 15 90deg]
606         D 0008|103e [LO]  [Series Description ] [fl2d9_line PA 15 0deg ]
607         (everything is flagged as 'ROW')
608       */      
609          if ( stationName == "MRC35150" )
610          {
611             if ( memcmp(seriesDescription.c_str(), "fl2d9linePA1590deg", 18) )
612               chSessionIndex = "1";
613             else if ( memcmp(seriesDescription.c_str(), "fl2d9linePA150deg", 18) )
614               chSessionIndex = "2"; 
615             else
616             {
617                std::cout << "====================== seriesDescription "
618                          << " neither fl2d9_line PA 15 90deg nor fl2d9_line PA 15 0deg (?!?) : ["
619                          << seriesDescription << "]" << std::endl;
620                chSessionIndex = "1";
621             }    
622          } 
623          else  // for all other 'normal' cases
624          {
625             if (currentPhaseEncodingDirection == "COL" || currentPhaseEncodingDirection == "COL " || currentPhaseEncodingDirection == " COL")
626                chSessionIndex = "1";
627             else if (currentPhaseEncodingDirection == "ROW" || currentPhaseEncodingDirection == "ROW "|| currentPhaseEncodingDirection == " ROW")
628                chSessionIndex = "2"; 
629             else
630             {
631                std::cout << "====================== PhaseEncodingDirection "
632                          << " neither COL nor ROW (?!?) : [ "
633                          << currentPhaseEncodingDirection << "]" << std::endl;
634                chSessionIndex = "1";
635             }
636          }
637       }
638       if (currentFile->IsVRCoherent(0x0020) == 1 )     
639          currentFile->InsertEntryString(chSessionIndex, 0x0020, 0x0012, "  ");
640       else
641          currentFile->InsertEntryString(chSessionIndex, 0x0020, 0x0012, "IS");
642  
643       // Deal with  0x0021, 0x1020 : 'SLICE INDEX'
644       char chSliceIndex[5];
645       sprintf(chSliceIndex, "%04d", sliceIndex);
646       std::string strChSliceIndex(chSliceIndex);
647        
648       // Deal with  0x0021, 0x1040 : 'FRAME INDEX' 
649       char chFrameIndex[5];
650       sprintf(chFrameIndex, "%04d", frameIndex);
651
652       std::string stringVR;       
653       if (currentFile->IsVRCoherent(0x0021) == 1 )
654          stringVR = "  ";
655       else
656         stringVR = "IS";
657   
658       currentFile->InsertEntryString(strChSliceIndex, 0x0021, 0x1020, stringVR);
659       currentFile->InsertEntryString(chFrameIndex,    0x0021, 0x1040, stringVR); 
660  
661  
662       std::string strImagePositionPatient    = currentFile->GetEntryString(0x0020, 0x0032 );
663       if (strImagePositionPatient == GDCM_NAME_SPACE::GDCM_UNFOUND)
664       {
665          if (verbose)
666             std::cout << "Duplicate ImagePosition into ImagePositionPatient" << std::endl;
667          currentFile->InsertEntryString(currentFile->GetEntryString(0x0020, 0x0030), 0x0020, 0x0032, "DS" );
668       }  
669       
670       std::string strImageOrientationPatient = f->GetEntryString(0x0020, 0x0037 );
671       if (strImageOrientationPatient == GDCM_NAME_SPACE::GDCM_UNFOUND)
672       {
673          if (verbose)
674             std::cout << "Duplicate ImageOrientation into ImageOrientationPatient" << std::endl;      
675          currentFile->InsertEntryString(currentFile->GetEntryString(0x0020, 0x0035), 0x0020, 0x0037, "DS" );       
676       }
677                 
678       if (taggrid)
679          frameIndex++;
680       else     
681       {     
682          if (flag == 0)
683          {       
684             flag = 1;
685          }
686          else
687          {
688             frameIndex++;
689             flag = 0;
690          }
691       } 
692       if (verbose)
693          std::cout << "Frame Index : " << frameIndex << std::endl; 
694                  
695       if (split)
696       
697          //fullWriteFilename = currentPhaseEncodingDirectionWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR 
698          //                                + lastFilename + strExtent;      
699          fullWriteFilename = currentPositionWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR 
700                                          + lastFilename + strExtent; 
701       else
702          fullWriteFilename = currentPatientWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR 
703                                          + lastFilename + strExtent; 
704       
705       /*           
706       systemCommand  = "cp " + fullFilename + " " + fullWriteFilename;
707       std::cout << systemCommand << std::endl;
708       system (  systemCommand.c_str() );
709       */
710             
711       // Load the pixels in RAM.    
712       
713       fh = GDCM_NAME_SPACE::FileHelper::New(currentFile);     
714       uint8_t *imageData = fh->GetImageDataRaw(); // Don't convert (Gray Pixels + LUT) into (RGB pixels) ?!?
715       fh->SetWriteTypeToDcmExplVR();
716       // We didn't modify pixels -> keep unchanged the following :
717       // 'Media Storage SOP Class UID' (0x0002,0x0002)
718       // 'SOP Class UID'               (0x0008,0x0016)
719       // 'Image Type'                  (0x0008,0x0008)
720       // 'Conversion Type'             (0x0008,0x0064)
721       
722       // Put to Black the burnt-in number.
723       nX = currentFile->GetXSize();
724       nY = currentFile->GetYSize();
725       for(int y=nY-15; y<nY; y++)
726          for(int x=nX/3; x<nX/2+50; x++)
727            imageData[ y*nX*2 + x ] = 0;   
728         
729       fh->SetContentType(GDCM_NAME_SPACE::UNMODIFIED_PIXELS_IMAGE);
730       if (!fh->Write(fullWriteFilename))
731       {
732          std::cout << "Fail to write :[" << fullWriteFilename << "]"
733                    << std::endl;
734       } 
735       fh->Delete();                
736    }
737    return 0;
738  }