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