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