21 #include <tclap/CmdLine.h> 25 #include <milxImage.h> 27 using namespace TCLAP;
29 typedef std::vector< std::string >::iterator stringiterator;
30 typedef std::vector< std::vector< std::string > >::iterator listiterator;
31 typedef std::vector< std::pair<std::string, std::string> >::iterator tagiterator;
34 enum operations {none = 0, info, convert, print, csv};
37 typedef unsigned char charPixelType;
38 typedef itk::Image<charPixelType, milx::imgDimension> charImageType;
39 typedef short shortPixelType;
40 typedef itk::Image<shortPixelType, milx::imgDimension> shortImageType;
41 typedef unsigned short ushortPixelType;
42 typedef itk::Image<ushortPixelType, milx::imgDimension> ushortImageType;
43 typedef int intPixelType;
44 typedef itk::Image<intPixelType, milx::imgDimension> intImageType;
45 typedef unsigned int uintPixelType;
46 typedef itk::Image<intPixelType, milx::imgDimension> uintImageType;
47 typedef float floatPixelType;
48 typedef itk::Image<floatPixelType, milx::imgDimension> floatImageType;
49 typedef itk::VectorImage<floatPixelType, milx::imgDimension> vectorImageType;
58 int main(
int argc,
char *argv[])
62 milx::PrintInfo(
"--------------------------------------------------------");
66 milx::PrintInfo(
"Supported Pixel/Voxel Types: Float, Short, UShort, Int, UInt, UChar, Vector.");
67 milx::PrintInfo(
"Use suffix argument to set output format for conversions. Default is Nifti (.nii.gz)");
69 milx::PrintInfo(
"Australian e-Health Research Centre, CSIRO, Australia.");
70 milx::PrintInfo(
"--------------------------------------------------------\n");
74 CmdLine cmd(
"A diagnostic tool for DICOM series operations",
' ',
milx::NumberToString(milx::Version));
77 ValueArg<std::string> outputArg(
"o",
"output",
"Output Image",
false,
"result.nii.gz",
"Output");
78 ValueArg<std::string> prefixArg(
"p",
"prefix",
"Output prefix for multiple output.",
false,
"img_",
"Output Prefix");
79 ValueArg<std::string> suffixArg(
"s",
"suffix",
"Output suffix for output format and additional text.",
false,
".nii.gz",
"Output Suffix");
80 ValueArg<std::string> exportArg(
"e",
"export-tags",
"Output DICOM tags as text pairs to file.",
false,
"tags.csv",
"Export Tags");
85 SwitchArg infoArg(
"",
"info",
"Report the image information(s) for each image in the DICOM series.",
false);
86 SwitchArg convertArg(
"c",
"convert",
"Convert the DICOM series to image volumes given at output.",
false);
87 SwitchArg printArg(
"t",
"print-tags",
"Output DICOM tags as text pairs in terminal.",
false);
88 SwitchArg recursiveArg(
"r",
"recursive",
"Recursively parse series directory provided.",
false);
89 SwitchArg instanceArg(
"",
"instance",
"Add Instance ID to filename if found.",
false);
90 SwitchArg echoArg(
"",
"echo",
"Add Echo ID to filename if found.",
false);
91 SwitchArg acquisitionArg(
"",
"acquisition",
"Add Acquisition ID to filename if found.",
true);
92 SwitchArg nocaseIDArg(
"",
"nocase",
"Ignore case ID in filename etc.",
false);
95 UnlabeledMultiArg<std::string> multinames(
"series",
"DICOM Image series to operate on",
true,
"Series");
98 cmd.add( multinames );
100 cmd.add( prefixArg );
101 cmd.add( suffixArg );
102 cmd.add( recursiveArg );
103 cmd.add( instanceArg );
105 cmd.add( acquisitionArg );
106 cmd.add( nocaseIDArg );
108 std::vector<Arg*> xorlist;
109 xorlist.push_back(&infoArg);
110 xorlist.push_back(&convertArg);
111 xorlist.push_back(&printArg);
112 xorlist.push_back(&exportArg);
114 #if (ITK_REVIEW || ITK_VERSION_MAJOR > 3) //Review only members 120 cmd.parse( argc, argv );
124 std::vector<std::string> filenames = multinames.getValue();
125 std::string outputName = outputArg.getValue();
126 const std::string prefixName = prefixArg.getValue();
127 const std::string suffixName = suffixArg.getValue();
128 const std::string exportName = exportArg.getValue();
129 const bool recurse = recursiveArg.isSet();
132 operations operation = none;
133 bool outputRequired =
false;
134 bool multiOutputRequired =
true;
137 outputRequired =
false;
138 multiOutputRequired =
false;
143 if(convertArg.isSet())
145 if(outputArg.isSet())
152 outputRequired =
true;
153 multiOutputRequired =
false;
158 if(exportArg.isSet())
169 std::cout <<
"Total Folders: " << filenames.size() << std::endl;
170 if(filenames.empty())
175 for(stringiterator name = filenames.begin(); name != filenames.end(); name ++)
176 std::cout << *name <<
", ";
177 std::cout << std::endl;
181 std::cerr <<
"Reading series UIDs" << std::endl;
182 std::vector< std::vector<std::string> > UIDList;
183 std::vector<std::string> validFilenames;
184 for (stringiterator name = filenames.begin(); name != filenames.end(); name++)
190 UIDList.push_back(UIDs);
191 validFilenames.push_back(*name);
194 std::cerr <<
"Done" << std::endl;
198 milx::PrintError(
"Found no series found in input directory. You may need to provide internal directory paths explicitly.");
204 for (dir = validFilenames.begin(), list = UIDList.begin(); list != UIDList.end(); list++, dir++)
206 std::cerr <<
"Applying operation to " << *dir << std::endl;
207 for (stringiterator name = list->begin(); name != list->end(); name++)
209 std::cerr <<
"Processing UID: " << *name << std::endl;
213 size_t dimensions = 3;
214 std::string pixelType, componentType;
217 milx::PrintError(
"Failed Reading First Image. Check the image type/file. Exiting.");
230 std::string echoID =
"";
231 std::string seriesID =
"";
232 std::string acqID =
"";
233 std::string instanceID =
"";
234 itk::SmartPointer<vectorImageType> vectorImage;
235 itk::SmartPointer<charImageType> labelledImage;
236 itk::SmartPointer<shortImageType> shortImage;
237 itk::SmartPointer<ushortImageType> ushortImage;
238 itk::SmartPointer<intImageType> intImage;
239 itk::SmartPointer<uintImageType> uintImage;
240 itk::SmartPointer<floatImageType> floatImage;
241 std::vector< std::pair<std::string, std::string> > tags;
242 bool labelledImages =
false, shortImages =
false, ushortImages =
false, integerImages =
false, uintegerImages =
false, vectorImages =
false;
243 if (pixelType ==
"vector" || dimensions > 3)
246 if (!milx::File::OpenDICOMSeriesAndTags<vectorImageType>(*dir, vectorImage, tags, *name, caseID, echoID, seriesID, acqID, instanceID, recurse))
253 else if (componentType ==
"unsigned_char" || componentType ==
"unsigned char")
256 if (!milx::File::OpenDICOMSeriesAndTags<charImageType>(*dir, labelledImage, tags, *name, caseID, echoID, seriesID, acqID, instanceID, recurse))
261 labelledImages =
true;
263 else if (componentType ==
"short" || componentType ==
"int16")
266 if (!milx::File::OpenDICOMSeriesAndTags<shortImageType>(*dir, shortImage, tags, *name, caseID, echoID, seriesID, acqID, instanceID, recurse))
273 else if (componentType ==
"unsigned_short" || componentType ==
"unsigned short")
276 if (!milx::File::OpenDICOMSeriesAndTags<ushortImageType>(*dir, ushortImage, tags, *name, caseID, echoID, seriesID, acqID, instanceID, recurse))
283 else if (componentType ==
"int" || componentType ==
"signed" || componentType ==
"int32" || componentType ==
"int64")
286 if (!milx::File::OpenDICOMSeriesAndTags<intImageType>(*dir, intImage, tags, *name, caseID, echoID, seriesID, acqID, instanceID, recurse))
291 integerImages =
true;
293 else if (componentType ==
"unsigned_int" || componentType ==
"unsigned int" || componentType ==
"unsigned")
296 if (!milx::File::OpenDICOMSeriesAndTags<uintImageType>(*dir, uintImage, tags, *name, caseID, echoID, seriesID, acqID, instanceID, recurse))
301 uintegerImages =
true;
306 if (!milx::File::OpenDICOMSeriesAndTags<floatImageType>(*dir, floatImage, tags, *name, caseID, echoID, seriesID, acqID, instanceID, recurse))
314 name->erase(std::remove(name->begin(),name->end(),
' '),name->end());
315 caseID.erase(std::remove(caseID.begin(),caseID.end(),
' '),caseID.end());
317 echoID.erase(std::remove(echoID.begin(),echoID.end(),
' '),echoID.end());
318 if(!seriesID.empty())
319 seriesID.erase(std::remove(seriesID.begin(),seriesID.end(),
' '),seriesID.end());
321 acqID.erase(std::remove(acqID.begin(),acqID.end(),
' '),acqID.end());
322 if(!instanceID.empty())
323 instanceID.erase(std::remove(instanceID.begin(),instanceID.end(),
' '),instanceID.end());
326 std::string path = caseID +
"/" + *name;
327 if(nocaseIDArg.isSet())
330 path +=
"_" + echoID;
331 if (prefixArg.isSet())
332 path = prefixName + path;
337 std::string filename = path +
"/" + caseID +
"_" + *name;
338 if(nocaseIDArg.isSet())
339 filename = path +
"/" + *name;
340 if(!echoID.empty() && echoArg.isSet())
341 filename +=
"_" + echoID;
342 if(!acqID.empty() && acquisitionArg.isSet())
343 filename +=
"_Acq_" + acqID;
344 if(!seriesID.empty())
345 filename +=
"_Series_" + seriesID;
346 if(!instanceID.empty() && instanceArg.isSet())
347 filename +=
"_Instance_" + instanceID;
348 filename += suffixName;
351 if(operation == print)
353 std::cout <<
"Tag \t| Value" << std::endl;
354 for (tagiterator tag = tags.begin(); tag != tags.end(); tag++)
355 std::cout << tag->first <<
"\t| " << tag->second << std::endl;
357 else if(operation == csv)
359 ofstream outFile(exportName.c_str(), ios::app);
361 for (tagiterator tag = tags.begin(); tag != tags.end(); tag++)
362 outFile << tag->first <<
"," << tag->second << std::endl;
377 milx::File::SaveImage<vectorImageType>(filename, vectorImage);
394 else if (labelledImages)
403 milx::File::SaveImage<charImageType>(filename, labelledImage);
420 else if (shortImages)
429 milx::File::SaveImage<shortImageType>(filename, shortImage);
446 else if (ushortImages)
455 milx::File::SaveImage<ushortImageType>(filename, ushortImage);
472 else if (integerImages)
481 milx::File::SaveImage<intImageType>(filename, intImage);
498 else if (uintegerImages)
507 milx::File::SaveImage<uintImageType>(filename, uintImage);
533 milx::File::SaveImage<floatImageType>(filename, floatImage);
550 std::cerr <<
"Done" << std::endl;
552 std::cerr <<
"Done" << std::endl;
void PrintDebug(const std::string msg)
Displays a generic msg to standard error with carriage return if in Debug mode.
static std::vector< std::string > GetDICOMSeriesFilenames(const std::string directoryPath, const std::string seriesName, bool recursive=false)
Returns the filenames for a given UID/Series name for a given directory.
void PrintError(const std::string msg)
Displays a generic msg to standard error with carriage return.
int main(int argc, char *argv[])
This program Animates image slices and animates surfaces in the model view for creating movies...
void PrintInfo(const std::string msg)
Displays a generic msg to standard output with carriage return.
std::string NumberToString(double num, unsigned zeroPad=0)
Number to string converter.
static void Information(itk::SmartPointer< TImage > img)
Prints the information of the image to standard output.
static bool ReadImageInformation(const std::string filename, std::string &pixeltype, std::string &componentType, size_t &dimensions)
Reads just the header of an image file (without reading the image data), and writes the info into the...
static std::vector< std::string > GetDICOMSeriesUIDs(const std::string directoryPath, bool recursive=false)
DICOM Related.
static void MakeDirectory(std::string name)
Creates directory (using ITK) if none exists.