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