]> Creatis software - gdcm.git/blob - Example/ToMRIregister.cxx
no message
[gdcm.git] / Example / ToMRIregister.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: ToMRIregister.cxx,v $
5   Language:  C++
6   Date:      $Date: 2011/03/29 07:35:58 $
7   Version:   $Revision: 1.6 $
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
19 #include "gdcmSerieHelper.h"
20 #include "gdcmFile.h"
21 #include "gdcmFileHelper.h"
22 #include "gdcmDebug.h"
23 #include "gdcmDirList.h"
24 #include "gdcmUtil.h"
25 #include "gdcmDataEntry.h"
26 #include "gdcmArgMgr.h"
27 #include <iostream>
28 #include <sstream>
29
30 bool AquisitionTime_0008_0032_Compare(GDCM_NAME_SPACE::File *file1, GDCM_NAME_SPACE::File *file2);
31
32 bool AquisitionTime_0008_0032_Compare(GDCM_NAME_SPACE::File *file1, GDCM_NAME_SPACE::File *file2)
33 {
34    return file1->GetEntryString(0x0008,0x0032) < file2->GetEntryString(0x0008,0x0032);
35 }
36
37 int main(int argc, char *argv[])
38 {  
39
40    START_USAGE(usage)
41    "\n ToMriregister :\n                                                      ",
42    " - Converts the Siemens Sonata MRI '*tfl2d1'                              ",
43    " to be processable by MriRegister software                                ",
44    " - May be used as a template for GDCM_NAME_SPACE::SerieHelper use.        ",
45    "                                                                          ",
46    "usage: ToMriRegister dirin=inputDirectoryName                             ",
47    "                     dirout=outputDirectoryName                           ",
48    "                     [ { [noshadowseq] | [noshadow][noseq] } ] [debug]    ",
49    "                                                                          ",
50    "       inputDirectoryName : user wants to analyze *all* the files         ",
51    "                            within the directory                          ",
52    "       noshadowseq: user doesn't want to load Private Sequences           ",
53    "       noshadow   : user doesn't want to load Private groups (odd number) ",
54    "       noseq      : user doesn't want to load Sequences                   ",
55    "       verbose    : user wants to run the program in 'verbose mode'       ",
56    "       debug      : developer wants to run the program in 'debug mode'    ",
57    FINISH_USAGE
58    
59    // ----- Initialize Arguments Manager ------
60   
61    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
62   
63    if (am->ArgMgrDefined("usage") || argc == 1) 
64    {
65       am->ArgMgrUsage(usage); // Display 'usage'
66       delete am;
67       return 0;
68    }
69
70    if (am->ArgMgrDefined("debug"))
71       GDCM_NAME_SPACE::Debug::DebugOn();
72
73    int verbose  = am->ArgMgrDefined("verbose");
74          
75    int loadMode = GDCM_NAME_SPACE::LD_ALL;
76    if ( am->ArgMgrDefined("noshadowseq") )
77       loadMode |= GDCM_NAME_SPACE::LD_NOSHADOWSEQ;
78    else 
79    {
80       if ( am->ArgMgrDefined("noshadow") )
81          loadMode |= GDCM_NAME_SPACE::LD_NOSHADOW;
82       if ( am->ArgMgrDefined("noseq") )
83          loadMode |= GDCM_NAME_SPACE::LD_NOSEQ;
84    }
85
86    const char *dirIn  = am->ArgMgrGetString("dirin");
87    if (dirIn == 0)
88    {
89        std::cout <<std::endl
90                  << "'dirin=' must be present;" 
91                  <<  std::endl;
92        am->ArgMgrUsage(usage); // Display 'usage'  
93        delete am;
94        return 0;
95    }
96
97    const char *dirOut  = am->ArgMgrGetString("dirout");
98    if (dirOut == 0)
99    {
100        std::cout <<std::endl
101                  << "'dirout=' must be present;" 
102                  <<  std::endl;
103        am->ArgMgrUsage(usage); // Display 'usage'  
104        delete am;
105        return 0;
106    }     
107        
108    /* if unused Param we give up */
109    if ( am->ArgMgrPrintUnusedLabels() )
110    {
111       am->ArgMgrUsage(usage);
112       delete am;
113       return 0;
114    } 
115  
116    delete am;  // ------ we don't need Arguments Manager any longer ------
117    
118    // ======================== more checking on the params ==============
119
120    if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirIn) )
121    {
122       std::cout << "KO : [" << dirIn << "] is not a Directory." << std::endl;
123       return 0;
124
125    }
126    else
127    {
128       if (verbose)     
129          std::cout << "OK : [" << dirIn << "] is a Directory." << std::endl;
130    }
131    
132    std::string systemCommand;
133    std::string strDirNameout(dirOut);          // to please gcc 4 
134    if (verbose)
135       std::cout << "Check for output directory :[" << dirOut << "]."
136              <<std::endl;
137    if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirOut) )    // dirout not found
138    {
139       systemCommand = "mkdir " + strDirNameout;   // create it!
140       if (verbose)
141          std::cout << systemCommand << std::endl;
142       system (systemCommand.c_str());
143       if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirOut) ) // be sure it worked
144       {
145           std::cout << "KO : not a dir : [" << dirOut 
146                     << "] (creation failure ?)" << std::endl;
147       return 0;
148
149       }
150       else
151       {
152         if (verbose)
153            std::cout << "Directory [" << dirOut << "] created." << std::endl;
154       }
155    }
156    else
157    {
158       if (verbose)
159          std::cout << "Output Directory [" << dirOut 
160                    << "] already exists; Used as is." << std::endl;
161    } 
162    
163    // ========================== Now, we can do the job! ================     
164                  
165    // Just to see *all* the file names:
166    
167    GDCM_NAME_SPACE::DirList dirList(dirIn,true); // gets (recursively) the file list
168    GDCM_NAME_SPACE::DirListType fileList = dirList.GetFilenames();
169    for( GDCM_NAME_SPACE::DirListType::iterator it  = fileList.begin();
170                                  it != fileList.end();
171                                  ++it )
172    {
173       std::cout << "file [" << it->c_str() << "]" << std::endl;  
174    }
175    
176    GDCM_NAME_SPACE::SerieHelper *s;
177   
178    s = GDCM_NAME_SPACE::SerieHelper::New();
179    s->SetLoadMode(GDCM_NAME_SPACE::LD_NOSEQ);     // Don't load Sequences
180  
181    // we could choose to ignore some Files  
182    //GDCM_NAME_SPACE::TagKey t(0x0010,0x0024);  // [Sequence Name]
183    // Keep only files where restriction is true
184    //s->AddRestriction(t, "*tfl2d1 ", GDCM_NAME_SPACE::GDCM_EQUAL); 
185                                                     
186    s->SetDirectory(dirIn, true); // true : recursive exploration
187
188 /*
189    std::cout << " ---------------------------------------- "
190              << "'Single UID' Filesets found in :["
191              << dirName << "]" << std::endl;
192
193    s->Print();
194    std::cout << " ------------------------------------- Result after splitting"
195              << std::endl;
196 */
197    int nbFiles;
198    std::string fullFilename, lastFilename;
199    char fullWriteFilename[1024]; // should be enough.
200
201    std::ostringstream str;
202   
203    GDCM_NAME_SPACE::XCoherentFileSetmap xcm;
204    GDCM_NAME_SPACE::FileHelper *fh;
205    
206    // will be used for ordering.
207    s->SetUserLessThanFunction(AquisitionTime_0008_0032_Compare);
208    int serieNumber = 0;
209    int sliceNumber = 0;
210    int imageNumber = 0;
211          
212    // For all the Single SerieUID Files Sets of the GDCM_NAME_SPACE::Serie
213    GDCM_NAME_SPACE::FileList *l = s->GetFirstSingleSerieUIDFileSet();
214    
215    char numero[5];
216    while (l)
217    {   
218       nbFiles = l->size() ;
219       if ( l->size() < 8 ) // Hope we skip Scout views !
220       {
221          std::cout << "Ignore the 'Single SerieUID' FileSet :[" 
222                    << s->GetCurrentSerieUIDFileSetUID()
223                    << "]  " << nbFiles << " long" << std::endl;
224          std::cout << "-----------------------------------" << std::endl;      
225       }
226       else
227       {
228          std::cout << "Split the 'Single SerieUID' FileSet :[" 
229                    << s->GetCurrentSerieUIDFileSetUID()
230                    << "]  " << nbFiles << " long" << std::endl;
231          std::cout << "-----------------------------------" << std::endl;
232
233          xcm = s->SplitOnPosition(l);
234     
235          //int sliceNumber = 0; 
236          
237          double position =0.0;
238          char charPosition[10];
239          
240          for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin();
241                                                   i != xcm.end();
242                                                 ++i)
243          {
244              std::cout << "Position : ";    
245              std::cout << "[" << (*i).first << "]" << std::endl;
246    
247             s->OrderFileList((*i).second);  // sort the current XCoherent Fileset
248     
249             position = position + 1.0;
250             sprintf(charPosition, "%f", position);
251             
252             //int imageNumber = 0;    
253             for ( GDCM_NAME_SPACE::FileList::iterator it =  ((*i).second)->begin();
254                                            it != ((*i).second)->end();
255                                          ++it)
256             {
257     
258             // Set the DataElements MriRegister needs to be happy
259             // Probabely one of the following (check it !):
260             /*
261                0020 0011 IS 1 Series Number
262                0020 0012 IS 1 Acquisition Number
263                0020 0013 IS 1 Instance Number
264            */
265
266            /*
267             Sure it needs ACR-NEMA elements : Study ID                20, 10 ?
268                                               Image Number            20, 12 ?
269                                               Location ('atof-able') -> 20, 50 ?    
270            */     
271             (*it)->InsertEntryString(charPosition,0x0020,0x0050, "DS");
272    
273            
274             (*it)->InsertEntryString("0",0x0008,0x0000, "UL"); // Needs to be present (actual length doesn't matter !)    
275
276             str.str("");
277             str << serieNumber;
278             (*it)->InsertEntryString(str.str(),0x0020,0x0011, "IS"); // Series Number
279
280            /*
281             str.str("");
282             str << imageNumber;
283             (*it)->InsertEntryString(str.str(),0x0020,0x0012, "IS"); // Acquisition Number
284             (*it)->InsertEntryString(str.str(),0x0020,0x0013, "IS"); // Instance Number
285            */
286    
287    sprintf(numero, "%04d", imageNumber);
288    (*it)->InsertEntryString(numero,0x0020,0x0012, "IS"); // Acquisition Number   
289    (*it)->InsertEntryString(numero,0x0020,0x0013, "IS"); // Instance Number
290  
291             // Load the pixels in RAM.    
292       
293                fh = GDCM_NAME_SPACE::FileHelper::New(*it);     
294                uint8_t *imageData = fh->GetImageDataRaw(); // Don't convert (Gray Pixels + LUT) into (RGB pixels) ?!?
295                if (!imageData)
296                   std::cout << "fail to read [" << (*it)->GetFileName() << std::endl;
297                fh->SetWriteTypeToAcr();  
298                fh->SetContentType(GDCM_NAME_SPACE::UNMODIFIED_PIXELS_IMAGE);
299     
300                // forge the file name
301       
302                fullFilename = (*it)->GetFileName();
303                lastFilename =  GDCM_NAME_SPACE::Util::GetName( fullFilename );
304                //fullWriteFilename = strDirNameout + GDCM_NAME_SPACE::GDCM_FILESEPARATOR 
305                //                                  + lastFilename;
306                sprintf(fullWriteFilename, "%s%c%04d-%04d-%04d.dcm", 
307                                       dirOut, GDCM_NAME_SPACE::GDCM_FILESEPARATOR,
308                                       serieNumber, sliceNumber, imageNumber);
309
310                if (verbose)
311                {
312                  // show [sliceLocation 0x0020,1041 (if any)] old name, -> newname
313                  std::string strSliceLocation;
314                  /*  
315                  GDCM_NAME_SPACE::DataEntry e = (*it)->GetDataEntry(0x0020,0x1041);
316                  if (e)
317                     strSliceLocation = e->GetString();
318                  else
319                     strSliceLocation = "";
320                  */ 
321                   strSliceLocation = (*it)->GetDataEntry(0x0020,0x1041)->GetString();   
322                   std::cout <<strSliceLocation << ": " << fullFilename << " -> " << fullWriteFilename << std::endl;
323                }
324                // Write it, now
325        
326                fh->SetWriteTypeToAcrLibido();
327        
328                if (!fh->Write(fullWriteFilename))
329                {
330                   std::cout << "Fail to write :[" << fullWriteFilename << "]"
331                             << std::endl;
332                }
333      
334                ///\todo FIXME segfaults if uncommented ?!?       
335                // delete(imageData);    
336                (*it)->Delete();
337                fh->Delete();
338       
339                imageNumber++;  
340        
341             } 
342             std::cout << std::endl; 
343             sliceNumber++;  
344          }
345       } 
346       serieNumber++;       
347       l = s->GetNextSingleSerieUIDFileSet();
348    }   
349    s->Delete();
350    return 0;
351 }