1 /*=========================================================================
4 Module: $RCSfile: exXCoherentFileSet.cxx,v $
6 Date: $Date: 2007/09/28 14:08:08 $
7 Version: $Revision: 1.11 $
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.
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.
17 =========================================================================*/
18 #include "gdcmSerieHelper.h"
20 #include "gdcmDebug.h"
22 #include "gdcmDirList.h"
25 #include "gdcmArgMgr.h"
27 void removeSpecChar(std::string &s);
29 void removeSpecChar(std::string &s) {
30 unsigned int s_size = s.size();
31 for(unsigned int i=0; i<s_size; i++)
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')))
41 s.replace(i, 1, "_"); // ImagePositionPatient related stuff will be more human readable
45 // deal with Dicom strings trailing '\0'
46 if(s[s_size-1] == '_')
51 int main(int argc, char *argv[])
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] ",
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' ",
83 // ----- Initialize Arguments Manager ------
85 GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
87 if (am->ArgMgrDefined("usage") || argc == 1)
89 am->ArgMgrUsage(usage); // Display 'usage'
94 if (am->ArgMgrDefined("debug"))
95 GDCM_NAME_SPACE::Debug::DebugOn();
97 int loadMode = GDCM_NAME_SPACE::LD_ALL;
98 if ( am->ArgMgrDefined("noshadowseq") )
99 loadMode |= GDCM_NAME_SPACE::LD_NOSHADOWSEQ;
102 if ( am->ArgMgrDefined("noshadow") )
103 loadMode |= GDCM_NAME_SPACE::LD_NOSHADOW;
104 if ( am->ArgMgrDefined("noseq") )
105 loadMode |= GDCM_NAME_SPACE::LD_NOSEQ;
108 const char *dirName = am->ArgMgrGetString("dirin");
111 std::cout <<std::endl
112 << "'dirin=' must be present;"
114 am->ArgMgrUsage(usage); // Display 'usage'
119 const char *dirNameout;
120 dirNameout = am->ArgMgrGetString("dirout",".");
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") );
129 if( (tag && (pos || ori)) || (pos && (tag || ori)) || (ori && (tag || pos)) )
131 std::cout << " POS, ORI and TAG are mutually exclusive" << std::endl;
136 if( (!tag && !pos && !ori))
138 std::cout << " One of POS, ORI and TAG is mandatory!" << std::endl;
146 groupelem = am->ArgMgrGetXInt16Enum("tag", &nb);
149 std::cout << "TAG : one and only one group,elem!" << std::endl;
155 /* if unused Param we give up */
156 if ( am->ArgMgrPrintUnusedLabels() )
158 am->ArgMgrUsage(usage);
163 delete am; // ------ we don't need Arguments Manager any longer ------
165 GDCM_NAME_SPACE::SerieHelper *s;
167 s = GDCM_NAME_SPACE::SerieHelper::New();
168 s->SetLoadMode(GDCM_NAME_SPACE::LD_ALL); // Load everything for each File
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
174 s->SetDirectory(dirName, true); // true : recursive exploration
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
182 std::cout << " ---------------------------------------- "
183 << "'Single UID' Filesets found in :["
184 << dirName << "]" << std::endl;
187 std::cout << " ------------------------------------- Result after splitting"
191 std::string systemCommand;
192 std::string filenameout;
195 std::cout << "Check for output directory :[" << dirNameout << "]."
197 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // dirout not found
199 std::string strDirNameout(dirNameout); // to please gcc 4
200 systemCommand = "mkdir " +strDirNameout; // create it!
202 std::cout << systemCommand << std::endl;
203 system (systemCommand.c_str());
204 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // be sure it worked
206 std::cout << "KO : not a dir : [" << dirNameout << "] (creation failure ?)"
213 std::cout << "Directory [" << dirNameout << "] created." << std::endl;
219 std::cout << "Output Directory [" << dirNameout
220 << "] already exists; Used as is."
225 // --> End of checking supposed-to-be-directory names
228 std::string fileName;
230 // For all the Single SerieUID Files Sets of the GDCM_NAME_SPACE::Serie
231 GDCM_NAME_SPACE::FileList *l = s->GetFirstSingleSerieUIDFileSet();
233 GDCM_NAME_SPACE::XCoherentFileSetmap xcm;
235 std::string serieUID;
236 std::string currentSerieWriteDir = "";
237 std::string xCoherentWriteDir = "";
238 std::string xCoherentName = "";
239 std::string serieDirectory;
240 std::string lastFilename;
242 int controlCount = 0;
243 while (l) // for each 'Single SerieUID FileSet'
245 nbFiles = l->size() ;
246 if ( l->size() > 0 ) // ignore Series with less than 2 images.
247 // Why not ? Just an example, for testing!
249 serieUID = s->GetCurrentSerieUIDFileSetUID();
250 removeSpecChar(serieUID);
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;
260 currentSerieWriteDir = currentSerieWriteDir + serieUID;
262 std::cout << "[" << currentSerieWriteDir<< "]" << std::endl;
263 // if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(currentSerieWriteDir) )
265 systemCommand = "mkdir " + currentSerieWriteDir;
266 system( systemCommand.c_str());
268 std::cout << "1 " <<systemCommand << std::endl;
273 std::cout << "Split the 'Single SerieUID' FileSet :["
275 << "] " << nbFiles << " long" << std::endl;
276 std::cout << "-----------------------------------" << std::endl;
279 xcm = s->SplitOnOrientation(l);
281 xcm = s->SplitOnPosition(l);
282 else if (groupelem != 0)
283 xcm = s->SplitOnTagValue(l, groupelem[0],groupelem[1] );
285 for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin();
289 xCoherentName = (*i).first;
291 std::cout << "xCoherentName = " << xCoherentName << std::endl;
292 removeSpecChar(xCoherentName);
296 xCoherentWriteDir = currentSerieWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR+ xCoherentName;
297 // if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(xCoherentWriteDir) )
299 systemCommand = "mkdir " + xCoherentWriteDir;
300 system( systemCommand.c_str());
302 std::cout << "2 " << systemCommand << std::endl;
308 std::cout << "Orientation : ";
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;
317 std::cout << "xCoherentName [" << xCoherentName << "]" << std::endl;
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.
325 s->OrderFileList((*i).second); // sort the XCoherent Fileset
326 std::cout << "ZSpacing for the file set " << s->GetZSpacing()
330 for (GDCM_NAME_SPACE::FileList::iterator it = ((*i).second)->begin();
331 it != ((*i).second)->end();
335 fileName = (*it)->GetFileName();
336 std::cout << " " << fileName << std::endl;
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());
346 std::cout << "3 " << systemCommand << std::endl;
350 std::cout << std::endl;
353 l = s->GetNextSingleSerieUIDFileSet();
356 if ( controlCount == 0 )
357 std::cout << "No suitable file was found!" << std::endl;