]> Creatis software - gdcm.git/blob - Example/exXCoherentFileSet.cxx
Normalization
[gdcm.git] / Example / exXCoherentFileSet.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: exXCoherentFileSet.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/09/28 14:08:08 $
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 "gdcmSerieHelper.h"
19 #include "gdcmFile.h"
20 #include "gdcmDebug.h"
21 #include <iostream>
22 #include "gdcmDirList.h"
23 #include "gdcmUtil.h"
24
25 #include "gdcmArgMgr.h"
26
27 void removeSpecChar(std::string &s);
28
29 void removeSpecChar(std::string &s) {
30       unsigned int s_size = s.size();
31       for(unsigned int i=0; i<s_size; i++)
32       {
33           if (
34          /*while(i<s_size
35                && */!( s[i] == '.' || s[i] == '%' || s[i] == '_'
36                  || (s[i] >= '+' && s[i] <= '-')       
37                  || (s[i] >= 'a' && s[i] <= 'z')
38                  || (s[i] >= '0' && s[i] <= '9')
39                  || (s[i] >= 'A' && s[i] <= 'Z')))
40          {
41             s.replace(i, 1, "_");  // ImagePositionPatient related stuff will be more human readable
42          }
43       }
44
45       // deal with Dicom strings trailing '\0' 
46       if(s[s_size-1] == '_')
47          s.erase(s_size-1, 1);
48
49 }
50      
51 int main(int argc, char *argv[])
52 {  
53
54    START_USAGE(usage)
55    "\n exXCoherentFileSet :\n                                                 ",
56    "Shows the various 'XCoherent' Filesets within a directory                 ",
57    "Optionaly copis the images in a Directories tree                          ",
58    "usage: exXCoherentFileSet {dirin=inputDirectoryName}                      ",
59    "                           dirout=outputDirectoryName                     ",
60    "                       { tag=group-elem | pos | ori } [sort] [write]      ",
61    "                       [ { [noshadowseq] | [noshadow][noseq] } ] [debug]  ",
62    "                                                                          ",
63    "       dirin : user wants to analyze *all* the files                      ",
64    "                            within the directory                          ",
65    "       write : user wants to create directories                           ",
66    "       dirout : will be created if doesn't exist                          ",
67    "       pos  : user wants to split each Single SerieUID Fileset on the     ",
68    "                         'Image Position '                                ",
69    "       ori  : user wants to split each Single SerieUID Fileset on the     ",
70    "                         'Image Orientation '                             ",
71    "       tag : group-elem    (in hexa, no space)                            ",
72    "                       the user wants to split on                         ",
73    "       sort :  user wants FileHelper to sort the images                   ",
74    "               Warning : will probabely crah if sort has no meaning       ",
75    "                (not only look at image names)                            ",
76    "       noshadowseq: user doesn't want to load Private Sequences           ",
77    "       noshadow   : user doesn't want to load Private groups (odd number) ",
78    "       noseq      : user doesn't want to load Sequences                   ",
79    "       verbose    : user wants to run the program in 'verbose mode'       ",   
80    "       debug      : developper wants to run the program in 'debug mode'   ",
81    FINISH_USAGE
82    
83    // ----- Initialize Arguments Manager ------
84   
85    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
86   
87    if (am->ArgMgrDefined("usage") || argc == 1) 
88    {
89       am->ArgMgrUsage(usage); // Display 'usage'
90       delete am;
91       return 0;
92    }
93
94    if (am->ArgMgrDefined("debug"))
95       GDCM_NAME_SPACE::Debug::DebugOn();
96       
97    int loadMode = GDCM_NAME_SPACE::LD_ALL;
98    if ( am->ArgMgrDefined("noshadowseq") )
99       loadMode |= GDCM_NAME_SPACE::LD_NOSHADOWSEQ;
100    else 
101    {
102       if ( am->ArgMgrDefined("noshadow") )
103          loadMode |= GDCM_NAME_SPACE::LD_NOSHADOW;
104       if ( am->ArgMgrDefined("noseq") )
105          loadMode |= GDCM_NAME_SPACE::LD_NOSEQ;
106    }
107
108    const char *dirName  = am->ArgMgrGetString("dirin");
109    if (dirName == 0)
110    {
111        std::cout <<std::endl
112                  << "'dirin=' must be present;" 
113                  <<  std::endl;
114        am->ArgMgrUsage(usage); // Display 'usage'  
115        delete am;
116        return 0;
117    }
118
119    const char *dirNameout;   
120    dirNameout  = am->ArgMgrGetString("dirout",".");
121
122    bool pos  =    ( 0 != am->ArgMgrDefined("pos") ); 
123    bool ori  =    ( 0 != am->ArgMgrDefined("ori") );   
124    bool sort =    ( 0 != am->ArgMgrDefined("sort") );
125    bool write =   ( 0 != am->ArgMgrDefined("write") );
126    bool verbose = ( 0 != am->ArgMgrDefined("verbose") );
127    bool tag     = ( 0 != am->ArgMgrDefined("tag") );
128
129    if( (tag && (pos || ori)) || (pos && (tag || ori)) || (ori && (tag || pos)) )
130    {
131       std::cout << " POS, ORI and TAG are mutually exclusive" << std::endl;
132       delete am;
133       return 0;      
134    }
135    
136    if( (!tag && !pos && !ori))
137    {
138       std::cout << " One of POS, ORI and TAG is mandatory!" << std::endl;
139       delete am;
140       return 0;      
141    }         
142    int nb;
143    uint16_t *groupelem;
144    if (tag)
145    {
146       groupelem = am->ArgMgrGetXInt16Enum("tag", &nb);
147       if (nb != 1)
148       {
149          std::cout << "TAG : one and only one group,elem!" << std::endl;
150          delete am;
151          return 0;
152       }
153    }      
154             
155    /* if unused Param we give up */
156    if ( am->ArgMgrPrintUnusedLabels() )
157    {
158       am->ArgMgrUsage(usage);
159       delete am;
160       return 0;
161    } 
162  
163    delete am;  // ------ we don't need Arguments Manager any longer ------
164    
165    GDCM_NAME_SPACE::SerieHelper *s;
166   
167    s = GDCM_NAME_SPACE::SerieHelper::New();
168    s->SetLoadMode(GDCM_NAME_SPACE::LD_ALL);     // Load everything for each File
169    
170    //GDCM_NAME_SPACE::TagKey t(0x0020,0x0013);   
171    //s->AddRestriction(t, "340", GDCM_NAME_SPACE::GDCM_LESS); // Keep only files where
172                                                               // restriction is true
173      
174    s->SetDirectory(dirName, true); // true : recursive exploration
175
176    // The Dicom file set is splitted into several 'Single SerieUID Files Sets'
177    // (a 'Single SerieUID Files Set' per SerieUID)
178    // In some cases, it's not enough, since, in some cases
179    // we can find scout view with the same SerieUID
180    
181 /*
182    std::cout << " ---------------------------------------- "
183              << "'Single UID' Filesets found in :["
184              << dirName << "]" << std::endl;
185
186    s->Print();
187    std::cout << " ------------------------------------- Result after splitting"
188              << std::endl;
189 */
190
191    std::string systemCommand;
192    std::string filenameout;   
193    if (write) { 
194       if (verbose)
195          std::cout << "Check for output directory :[" << dirNameout << "]."
196                    <<std::endl;
197       if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) )    // dirout not found
198       {
199          std::string strDirNameout(dirNameout);          // to please gcc 4
200          systemCommand = "mkdir " +strDirNameout;        // create it!
201          if (verbose)
202             std::cout << systemCommand << std::endl;
203          system (systemCommand.c_str());
204          if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // be sure it worked
205          {
206              std::cout << "KO : not a dir : [" << dirNameout << "] (creation failure ?)" 
207                        << std::endl;
208          return 0;
209          }
210          else
211          {
212             if (verbose)
213                std::cout << "Directory [" << dirNameout << "] created." << std::endl;
214          }
215       }
216       else
217       {
218          if (verbose)
219             std::cout << "Output Directory [" << dirNameout 
220                       << "] already exists; Used as is."
221                       << std::endl;
222       }      
223    }
224    
225       // --> End of checking supposed-to-be-directory names
226       
227    int nbFiles;
228    std::string fileName;
229    
230    // For all the Single SerieUID Files Sets of the GDCM_NAME_SPACE::Serie
231    GDCM_NAME_SPACE::FileList *l = s->GetFirstSingleSerieUIDFileSet();
232    
233    GDCM_NAME_SPACE::XCoherentFileSetmap xcm;
234    
235    std::string serieUID;
236    std::string currentSerieWriteDir = "";
237    std::string xCoherentWriteDir = ""; 
238    std::string xCoherentName = "";     
239    std::string serieDirectory;
240    std::string lastFilename;
241    
242    int controlCount = 0;    
243    while (l) // for each 'Single SerieUID FileSet'
244    { 
245       nbFiles = l->size() ;
246       if ( l->size() > 0 ) // ignore Series with less than 2 images.
247                            // Why not ? Just an example, for testing!
248       {
249           serieUID = s->GetCurrentSerieUIDFileSetUID();
250           removeSpecChar(serieUID);
251  
252           // --- for write
253           if (write)
254           {
255              currentSerieWriteDir = currentSerieWriteDir + dirNameout;
256              unsigned int l = strlen(dirNameout)-1;
257              if ( dirNameout[l] != '/'  &&  dirNameout[l] != '\\')
258                 currentSerieWriteDir = currentSerieWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR;
259     
260              currentSerieWriteDir = currentSerieWriteDir + serieUID;
261              if (verbose)
262                 std::cout << "[" << currentSerieWriteDir<< "]" << std::endl;
263             // if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(currentSerieWriteDir) )
264              {     
265                 systemCommand   = "mkdir " + currentSerieWriteDir;
266                 system( systemCommand.c_str());
267                 if (verbose)
268                    std::cout <<  "1 " <<systemCommand << std::endl;
269              }
270          } 
271           // --- end for write
272     
273          std::cout << "Split the 'Single SerieUID' FileSet :[" 
274                    << serieUID
275                    << "]  " << nbFiles << " long" << std::endl;
276          std::cout << "-----------------------------------" << std::endl;
277   
278          if (ori) 
279             xcm = s->SplitOnOrientation(l);
280          else if (pos)
281             xcm = s->SplitOnPosition(l);
282          else if (groupelem != 0)
283             xcm = s->SplitOnTagValue(l, groupelem[0],groupelem[1] );
284
285          for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin(); 
286                                                   i != xcm.end();
287                                                 ++i)
288          {
289              xCoherentName = (*i).first;
290             if (verbose)
291                std::cout << "xCoherentName = " << xCoherentName << std::endl;
292              removeSpecChar(xCoherentName);
293              // --- for write
294              if (write)
295              { 
296                 xCoherentWriteDir = currentSerieWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR+ xCoherentName;
297                // if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(xCoherentWriteDir) )
298                 {      
299                    systemCommand   = "mkdir " + xCoherentWriteDir;
300                    system( systemCommand.c_str());
301                    if (verbose)
302                       std::cout << "2 " << systemCommand << std::endl;       
303                 }
304             } 
305             // --- end for write
306     
307             if (ori) 
308                std::cout << "Orientation : ";
309             else if (pos) 
310                std::cout << "Position : ";
311             else if (groupelem != 0)    
312                std::cout << "Tag (" << std::hex << groupelem[0]
313                          << "|" << groupelem[1] << ") value : ";
314             std::cout << "[" << (*i).first << "]" << std::endl;
315         
316             if (verbose)
317                std::cout << "xCoherentName [" << xCoherentName << "]" << std::endl;
318     
319            // Within a 'just to see' program, 
320            // OrderFileList() causes trouble, since some files
321            // (eg:MIP views) don't have 'Position', now considered as mandatory
322            // Commented out for the moment.
323            
324            if (sort) {
325               s->OrderFileList((*i).second);  // sort the XCoherent Fileset
326               std::cout << "ZSpacing for the file set " << s->GetZSpacing()
327                         << std::endl;
328             } 
329
330             for (GDCM_NAME_SPACE::FileList::iterator it =  ((*i).second)->begin();
331                                           it != ((*i).second)->end();
332                                         ++it)
333             {
334                controlCount ++;
335                fileName = (*it)->GetFileName();
336                std::cout << "    " << fileName << std::endl;
337     
338                // --- for write
339                if (write)
340                {  
341                   lastFilename =  GDCM_NAME_SPACE::Util::GetName( fileName );
342                   filenameout = xCoherentWriteDir  + GDCM_NAME_SPACE::GDCM_FILESEPARATOR+ lastFilename; 
343                   systemCommand   = "cp " + fileName + " " + filenameout;
344                   system( systemCommand.c_str());
345                   if (verbose)
346                      std::cout << "3 " << systemCommand << std::endl;
347                 } 
348                // --- end for write       
349             } 
350             std::cout << std::endl;   
351          }
352       }
353       l = s->GetNextSingleSerieUIDFileSet();
354    }
355     
356    if ( controlCount == 0 )
357       std::cout << "No suitable file was found!" << std::endl;
358  
359    s->Delete();
360
361    return 0;
362 }