1 /*=========================================================================
4 Module: $RCSfile: SplitIntoXCoherentDirectories.cxx,v $
6 Date: $Date: 2011/08/25 14:37:05 $
7 Version: $Revision: 1.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.
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"
19 #include "gdcmFileHelper.h"
21 #include "gdcmDebug.h"
23 #include "gdcmDirList.h"
25 #include "gdcmArgMgr.h"
26 #include "gdcmDictSet.h" // for GetName
27 int main(int argc, char *argv[])
31 "\n SplitIntoXCoherentDirectories :\n ",
32 "Shows the various 'XCoherent' Filesets within a directory ",
33 "Optionaly copies the images in a Directories tree ",
34 "usage: exXCoherentFileSet {dirin=inputDirectoryName} ",
35 " dirout=outputDirectoryName ",
36 " { tag=group-elem | pos | ori } [sort] ",
37 " [{ write | copy }] [studyUID = ] ",
38 " [ { [noshadowseq] | [noshadow][noseq] } ] [debug] ",
40 " dirin : user wants to analyze *all* the files ",
41 " within the directory ",
42 " copy : user wants to copy the files into a directories tree ",
43 " write : user wants to rewrite the files into a directories tree ",
44 " each directory with the same 'Series Instance UID' ",
45 " dirout : will be created if doesn't exist ",
46 " pos : user wants to split each Single SerieUID Fileset on the ",
47 " 'Image Position ' ",
48 " ori : user wants to split each Single SerieUID Fileset on the ",
49 " 'Image Orientation ' ",
50 " tag : group-elem (in hexa, no space) ",
51 " the user wants to split on ",
52 " sort : user wants FileHelper to sort the images ",
53 " Warning : will probabely crash if sort has no meaning ",
54 " (not only look at image names) ",
55 " studyUID : *aware* user wants to add the serie ",
56 " to an already existing study ",
57 " verbose : user wants to run the program in 'verbose mode' ",
58 " debug : developper wants to run the program in 'debug mode' ",
61 // ----- Initialize Arguments Manager ------
63 GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
65 if (am->ArgMgrDefined("usage") || argc == 1)
67 am->ArgMgrUsage(usage); // Display 'usage'
72 if (am->ArgMgrDefined("debug"))
73 GDCM_NAME_SPACE::Debug::DebugOn();
78 const char *dirName = am->ArgMgrGetString("dirin");
82 << "'dirin=' must be present;"
84 am->ArgMgrUsage(usage); // Display 'usage'
89 const char *dirNameout;
90 dirNameout = am->ArgMgrGetString("dirout",".");
92 bool pos = ( 0 != am->ArgMgrDefined("pos") );
93 bool ori = ( 0 != am->ArgMgrDefined("ori") );
94 bool sort = ( 0 != am->ArgMgrDefined("sort") );
95 bool copy = ( 0 != am->ArgMgrDefined("copy") );
96 bool write = ( 0 != am->ArgMgrDefined("write") );
97 bool verbose = ( 0 != am->ArgMgrDefined("verbose") );
98 bool tag = ( 0 != am->ArgMgrDefined("tag") );
102 std::cout << "COPY and WRITE are mutually exclusive" << std::endl;
107 if( (tag && (pos || ori)) || (pos && (tag || ori)) || (ori && (tag || pos)) )
109 std::cout << " POS, ORI and TAG are mutually exclusive" << std::endl;
114 if( (!tag && !pos && !ori))
116 std::cout << " One of POS, ORI and TAG is mandatory!" << std::endl;
124 groupelem = am->ArgMgrGetXInt16Enum("tag", &nb);
127 std::cout << "TAG : one and only one group,elem!" << std::endl;
133 bool userDefinedStudy = ( 0 != am->ArgMgrDefined("userDefinedStudy") );
134 const char *studyUID = am->ArgMgrGetString("studyUID");
136 /* if unused Param we give up */
137 if ( am->ArgMgrPrintUnusedLabels() )
139 am->ArgMgrUsage(usage);
144 delete am; // ------ we don't need Arguments Manager any longer ------
147 GDCM_NAME_SPACE::SerieHelper *s;
148 s = GDCM_NAME_SPACE::SerieHelper::New();
150 GDCM_NAME_SPACE::File *f;
151 s->SetLoadMode(GDCM_NAME_SPACE::LD_ALL); // Load everything for each File
152 s->SetDirectory(dirName, true); // true : recursive exploration
154 GDCM_NAME_SPACE::DirList dirlist(dirName, true); // recursive exploration
155 GDCM_NAME_SPACE::DirListType fileNames = dirlist.GetFilenames();
156 GDCM_NAME_SPACE::FileList *l = new GDCM_NAME_SPACE::FileList;
158 std::string replaceChar("_");
159 // Loop on all the gdcm-readable files
160 for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin();
161 it != fileNames.end();
165 std::cout << *it << std::endl;
168 loadMode = GDCM_NAME_SPACE::LD_ALL; // load any DataElement
169 maxSize = 0x7fff; // load any length
171 loadMode = GDCM_NAME_SPACE::LD_NOSEQ | GDCM_NAME_SPACE::LD_NOSHADOW ;
175 f = GDCM_NAME_SPACE::File::New();
176 f->SetLoadMode(loadMode);
177 f->SetMaxSizeLoadEntry(maxSize);
178 f->SetFileName( *it );
183 std::string systemCommand;
184 std::string filenameout;
187 std::cout << "Check for output directory :[" << dirNameout << "]."
189 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // dirout not found
191 std::string strDirNameout(dirNameout); // to please gcc 4
192 systemCommand = "mkdir \"" +strDirNameout + "\""; // create it!
194 std::cout << systemCommand << std::endl;
195 system (systemCommand.c_str());
196 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // be sure it worked
198 std::cout << "KO : not a dir : [" << dirNameout << "] (creation failure ?)"
205 std::cout << "Directory [" << dirNameout << "] created." << std::endl;
211 std::cout << "Output Directory [" << dirNameout
212 << "] already exists; Used as is."
216 // --> End of checking supposed-to-be-directory names
219 std::string fileName;
221 // For all the Single SerieUID Files Sets of the GDCM_NAME_SPACE::Serie
223 // GDCM_NAME_SPACE::FileList *l = s->GetFirstSingleSerieUIDFileSet();
225 l = s->GetFirstSingleSerieUIDFileSet();
227 std::cout << "No Serie found ?!?" << std::endl;
231 GDCM_NAME_SPACE::XCoherentFileSetmap xcm;
233 std::string serieUID;
234 std::string currentSerieWriteDir = "";
235 std::string xCoherentWriteDir = "";
236 std::string xCoherentName = "";
237 std::string serieDirectory;
238 std::string lastFilename;
239 std::string rep("_");
240 int controlCount = 0;
242 // 'Study Instance UID'
243 // The user is allowed to create his own Study,
244 // keeping the same 'Study Instance UID' for various images
245 // The user may add images to a 'Manufacturer Study',
246 // adding new Series to an already existing Study
247 std::string strStudyUID;
249 if ( !userDefinedStudy )
250 strStudyUID = GDCM_NAME_SPACE::Util::CreateUniqueUID();
252 strStudyUID = studyUID;
255 while (l) // for each 'Single SerieUID FileSet' //===> Ignore 'Serie UID"
257 currentSerieWriteDir = "";
258 nbFiles = l->size() ;
259 if ( l->size() > 2 ) // ignore a Directory with less than 2 images.
260 // Why not ? Just an example, for testing!
262 // Just not to make too many modif in the code
263 //serieUID = "SingleSerie"; // s->GetCurrentSerieUIDFileSetUID();
264 serieUID = s->GetCurrentSerieUIDFileSetUID();
265 GDCM_NAME_SPACE::Util::ReplaceSpecChar(serieUID, rep);
270 currentSerieWriteDir = currentSerieWriteDir + dirNameout;
271 unsigned int l = strlen(dirNameout)-1;
272 if ( dirNameout[l] != '/' && dirNameout[l] != '\\')
273 currentSerieWriteDir = currentSerieWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR;
275 currentSerieWriteDir = currentSerieWriteDir + serieUID;
277 std::cout << "[" << currentSerieWriteDir<< "]" << std::endl;
278 // if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(currentSerieWriteDir) )
280 systemCommand = "mkdir \"" + currentSerieWriteDir + "\"";
281 system( systemCommand.c_str());
283 std::cout << "1 " <<systemCommand << std::endl;
288 std::cout << "Split the 'Single SerieUID' FileSet :["
290 << "] " << nbFiles << " long" << std::endl;
291 std::cout << "-----------------------------------" << std::endl;
294 xcm = s->SplitOnOrientation(l);
296 xcm = s->SplitOnPosition(l);
297 else if (groupelem != 0) {
298 // Crashes if DataElement not found
299 //std:: cout << GDCM_NAME_SPACE::Global::GetDicts()->GetDefaultPubDict()->GetEntry(groupelem[0],groupelem[1])->GetName() << std::endl;
301 xcm = s->SplitOnTagValue(l, groupelem[0],groupelem[1] );
304 GDCM_NAME_SPACE::FileHelper *fh;
306 for (GDCM_NAME_SPACE::XCoherentFileSetmap::iterator i = xcm.begin();
310 xCoherentName = (*i).first;
312 std::cout << "==========================================xCoherentName = " << xCoherentName << std::endl;
313 GDCM_NAME_SPACE::Util::ReplaceSpecChar(xCoherentName, rep);
317 xCoherentWriteDir = currentSerieWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR+ xCoherentName;
318 // if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(xCoherentWriteDir) )
320 systemCommand = "mkdir \"" + xCoherentWriteDir + "\"";
321 system( systemCommand.c_str());
323 std::cout << "2 " << systemCommand << std::endl;
329 std::cout << "Orientation : ";
331 std::cout << "Position : ";
332 else if (groupelem != 0)
333 std::cout << "Tag (" << std::hex << groupelem[0]
334 << "|" << groupelem[1] << ") value : ";
335 std::cout << "[" << (*i).first << "]" << std::endl;
338 std::cout << "xCoherentName [" << xCoherentName << "]" << std::endl;
340 // Within a 'just to see' program,
341 // OrderFileList() causes trouble, since some files
342 // (eg:MIP views) don't have 'Position', now considered as mandatory
343 // --> Activated on user demand.
346 s->OrderFileList((*i).second); // sort the XCoherent Fileset
347 std::cout << "ZSpacing for the file set " << s->GetZSpacing()
351 std::string strSerieUID = GDCM_NAME_SPACE::Util::CreateUniqueUID();
353 for (GDCM_NAME_SPACE::FileList::iterator it2 = ((*i).second)->begin();
354 it2 != ((*i).second)->end();
358 fileName = (*it2)->GetFileName();
360 lastFilename = GDCM_NAME_SPACE::Util::GetName( fileName );
362 // If you want to create file names of your own, here is the place!
363 // Just replace 'lastFilename' by anything that's better for you.
364 GDCM_NAME_SPACE:: Util::ReplaceSpecChar(lastFilename, replaceChar);
366 filenameout = xCoherentWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR+ lastFilename;
369 fh = GDCM_NAME_SPACE::FileHelper::New( (*it2) );
370 fh->SetKeepOverlays( true );
371 fh->InsertEntryString(strSerieUID,0x0020,0x000e,"UI");
372 unsigned int dataSize = fh->GetImageDataRawSize();
373 uint8_t *imageData = fh->GetImageDataRaw();// somewhat important : Loads the Pixels in memory !
375 std::cout << "fail to read [" << (*it2)->GetFileName() << std::endl;
376 fh->SetWriteTypeToDcmExplVR();
377 fh->SetContentType(GDCM_NAME_SPACE::UNMODIFIED_PIXELS_IMAGE);
378 if (!fh->Write(filenameout))
380 std::cout << "Fail to write :[" << filenameout << "]"
387 systemCommand = "cp \"" + fileName + "\" \"" + filenameout + "\"";
388 system( systemCommand.c_str());
391 std::cout << "3 " << systemCommand << std::endl;
394 std::cout << std::endl;
396 l = s->GetNextSingleSerieUIDFileSet();
399 if ( controlCount == 0 )
400 std::cout << "No suitable file was found!" << std::endl;