23 #include <itksys/SystemTools.hxx> 24 #include <tinyxml/tinyxml.h> 26 struct InputParameters
31 std::string settingsFile;
32 std::string imageType;
35 struct BandpassSettings
54 struct ResampleSettings
66 struct ProcessSettings
79 parser.
setTitle(
"Mitk Photoacoustics Beamforming Tool");
80 parser.
setDescription(
"Reads a nrrd file as an input and applies a beamforming method as set with the parameters defined in an additionally provided xml file.");
81 parser.
setContributor(
"Computer Assisted Medical Interventions, DKFZ");
88 "Input image (mitk::Image)",
"input image (.nrrd file)",
92 "Output filename",
"output image (.nrrd file)",
96 "settings file",
"file containing beamforming and other specifications(.xml file)",
100 "image type",
"Specifies whether to use the PA or US subsection of the xml file must be 'PA' or 'US'",
107 "Verbose Output",
"Whether to produce verbose, or rather debug output. (default: false)");
110 InputParameters input;
112 std::map<std::string, us::Any> parsedArgs = parser.
parseArguments(argc, argv);
113 if (parsedArgs.size() == 0)
116 input.verbose = (bool)parsedArgs.count(
"verbose");
117 MITK_INFO(input.verbose) <<
"### VERBOSE OUTPUT ENABLED ###";
119 if (parsedArgs.count(
"inputImage"))
121 MITK_INFO(input.verbose) <<
"Reading input image...";
122 input.inputImage = mitk::IOUtil::Load<mitk::Image>(
us::any_cast<std::string>(parsedArgs[
"inputImage"]));
123 MITK_INFO(input.verbose) <<
"Reading input image...[Done]";
128 if (parsedArgs.count(
"output"))
129 input.outputFilename = us::any_cast<std::string>(parsedArgs[
"output"]);
131 mitkThrow() <<
"No output image path given..";
133 if (parsedArgs.count(
"settings"))
134 input.settingsFile = us::any_cast<std::string>(parsedArgs[
"settings"]);
136 mitkThrow() <<
"No settings image path given..";
138 if (parsedArgs.count(
"type"))
139 input.imageType = us::any_cast<std::string>(parsedArgs[
"type"]);
141 mitkThrow() <<
"No settings image type given..";
148 for (TiXmlElement* elem = root->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement())
150 if (elem->Value() == childName)
156 void ParseXML(std::string xmlFile, InputParameters input, mitk::BeamformingSettings::Pointer *bfSet, BandpassSettings& bandpassSet, CropSettings& cropSet, ResampleSettings& resSet, BModeSettings& bmodeSet, ProcessSettings& processSet)
158 MITK_INFO <<
"Loading configuration File \"" << xmlFile <<
"\"";
159 TiXmlDocument doc(xmlFile);
161 mitkThrow() <<
"Failed to load settings file \"" << xmlFile <<
"\" Error: " << doc.ErrorDesc();
163 TiXmlElement* root = doc.FirstChildElement();
166 mitkThrow() <<
"Failed to load file: No root element.";
170 TiXmlElement* elemtop =
getRootChild(root, input.imageType);
171 if(elemtop ==
nullptr)
172 mitkThrow() <<
"The xml file is wrongly formatted, no element \"" << input.imageType <<
"\" found";
174 for (TiXmlElement* elem = elemtop->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement())
176 std::string elemName = elem->Value();
177 if (elemName ==
"Beamforming")
179 processSet.DoBeamforming = std::stoi(elem->Attribute(
"do"));
180 if (!processSet.DoBeamforming)
183 float SpeedOfSound = std::stof(elem->Attribute(
"speedOfSoundMeterPerSecond"));
184 float PitchMeter = std::stof(elem->Attribute(
"pitchMilliMeter"))/1000;
185 float TimeSpacingMicroSecond = (float)(input.inputImage->GetGeometry()->GetSpacing()[1] / 1000000);
187 if (std::stof(elem->Attribute(
"timeSpacingMicroSecond")) > 0) {
188 TimeSpacingMicroSecond = std::stof(elem->Attribute(
"timeSpacingMicroSecond"));
189 MITK_INFO <<
"TIME: " << TimeSpacingMicroSecond;
192 float Angle = std::stof(elem->Attribute(
"apodizationAngle"));
193 bool IsPhotoacousticImage =
true;
194 if (std::string(elem->Attribute(
"imageType")).
compare(
"US") == 0) {
195 IsPhotoacousticImage =
false;
199 unsigned int SamplesPerLine = std::stoi(elem->Attribute(
"reconstructedYDimension"));
200 unsigned int ReconstructionLines = std::stoi(elem->Attribute(
"reconstructedXDimension"));
203 float ReconstructionDepth = std::stof(elem->Attribute(
"reconstructionDepthMeter"));
204 bool UseGPU = std::stoi(elem->Attribute(
"useGPU"));
205 unsigned int GPUBatchSize = std::stoi(elem->Attribute(
"GPUBatchSize"));
207 std::string apodizationStr = elem->Attribute(
"apodizationFunction");
209 if (apodizationStr ==
"Box")
210 Apodization = mitk::BeamformingSettings::Apodization::Box;
211 else if (apodizationStr ==
"Hann")
212 Apodization = mitk::BeamformingSettings::Apodization::Hann;
213 else if (apodizationStr ==
"Hamm")
214 Apodization = mitk::BeamformingSettings::Apodization::Hamm;
216 mitkThrow() <<
"Apodization incorrectly defined in settings";
218 std::string geomStr = elem->Attribute(
"probeGeometry");
220 if (geomStr ==
"linear")
222 else if(geomStr ==
"concave")
223 ProbeGeometry = mitk::BeamformingSettings::ProbeGeometry::Concave;
225 mitkThrow() <<
"geometry incorrectly defined in settings";
227 float radius = std::stof(elem->Attribute(
"radiusMilliMeter"))/1000;
229 unsigned int ApodizationArraySize = ReconstructionLines;
231 std::string algorithmStr = elem->Attribute(
"algorithm");
233 if (algorithmStr ==
"DAS")
234 Algorithm = mitk::BeamformingSettings::BeamformingAlgorithm::DAS;
235 else if (algorithmStr ==
"DMAS")
236 Algorithm = mitk::BeamformingSettings::BeamformingAlgorithm::DMAS;
237 else if (algorithmStr ==
"sDMAS")
238 Algorithm = mitk::BeamformingSettings::BeamformingAlgorithm::sDMAS;
240 mitkThrow() <<
"Beamforming algorithm incorrectly defined in settings";
245 TimeSpacingMicroSecond,
247 IsPhotoacousticImage,
250 input.inputImage->GetDimensions(),
255 ApodizationArraySize,
261 if (elemName ==
"Bandpass")
263 processSet.DoBandpass = std::stoi(elem->Attribute(
"do"));
264 if (!processSet.DoBandpass)
267 bandpassSet.highPass = std::stof(elem->Attribute(
"highPass"));
268 bandpassSet.lowPass = std::stof(elem->Attribute(
"lowPass"));
269 bandpassSet.alphaLow = std::stof(elem->Attribute(
"alphaLow"));
270 bandpassSet.alphaHigh = std::stof(elem->Attribute(
"alphaHigh"));
272 if (elemName ==
"Cropping")
274 processSet.DoCropping = std::stoi(elem->Attribute(
"do"));
275 if (!processSet.DoCropping)
278 cropSet.above = std::stoi(elem->Attribute(
"cutAbove"));
279 cropSet.below = std::stoi(elem->Attribute(
"cutBelow"));
280 cropSet.right = std::stoi(elem->Attribute(
"cutRight"));
281 cropSet.left = std::stoi(elem->Attribute(
"cutLeft"));
282 cropSet.zStart = std::stoi(elem->Attribute(
"firstSlice"));
283 cropSet.zEnd = std::stoi(elem->Attribute(
"cutSlices"));
285 if (elemName ==
"Resampling")
287 processSet.DoResampling = std::stoi(elem->Attribute(
"do"));
288 if (!processSet.DoResampling)
291 resSet.spacing = std::stod(elem->Attribute(
"spacing"));
292 resSet.dimX = std::stoi(elem->Attribute(
"dimX"));
294 if (elemName ==
"BMode")
296 processSet.DoBmode = std::stoi(elem->Attribute(
"do"));
297 if (!processSet.DoBmode)
300 std::string methodStr = elem->Attribute(
"method");
301 if (methodStr ==
"EnvelopeDetection")
302 bmodeSet.method = mitk::PhotoacousticFilterService::BModeMethod::EnvelopeDetection;
303 else if (methodStr ==
"Abs")
304 bmodeSet.method = mitk::PhotoacousticFilterService::BModeMethod::Abs;
306 mitkThrow() <<
"BMode method incorrectly set in configuration file";
307 bmodeSet.UseLogFilter = (bool)std::stoi(elem->Attribute(
"useLogFilter"));
312 int main(
int argc,
char * argv[])
316 mitk::BeamformingSettings::Pointer bfSettings;
317 BandpassSettings bandpassSettings{5,10,1,1,1540};
318 BModeSettings bmodeSettings{ mitk::PhotoacousticFilterService::BModeMethod::EnvelopeDetection,
false };
319 CropSettings cropSettings{ 0,0,0,0,0,0 };
320 ResampleSettings resSettings{ 0.15 , 256};
321 ProcessSettings processSettings{
false,
false,
false,
false,
false };
326 ParseXML(input.settingsFile, input, &bfSettings, bandpassSettings, cropSettings, resSettings, bmodeSettings, processSettings);
334 MITK_INFO <<
"Parsing settings XML...[Done]";
336 MITK_INFO(input.verbose) <<
"Beamforming input image...";
338 if (!(inputImage->GetPixelType().GetTypeAsString() ==
"scalar (float)" || inputImage->GetPixelType().GetTypeAsString() ==
" (float)"))
341 MITK_INFO(input.verbose) <<
"Casting input image to float...";
343 castFilter->SetInput(inputImage);
344 castFilter->Update();
345 inputImage = castFilter->GetOutput();
346 MITK_INFO << inputImage->GetPixelType().GetPixelTypeAsString();
347 MITK_INFO(input.verbose) <<
"Casting input image to float...[Done]";
353 if (processSettings.DoBandpass)
355 MITK_INFO(input.verbose) <<
"Bandpassing input image...";
356 output = m_FilterService->ApplyBandpassFilter(output, bandpassSettings.highPass*1e6, bandpassSettings.lowPass*1e6, bandpassSettings.alphaHigh, bandpassSettings.alphaLow, 1, bandpassSettings.speedOfSound,
true);
357 MITK_INFO(input.verbose) <<
"Bandpassing input image...[Done]";
359 if (processSettings.DoBeamforming)
361 MITK_INFO(input.verbose) <<
"Beamforming input image...";
362 output = m_FilterService->ApplyBeamforming(output, bfSettings);
363 MITK_INFO(input.verbose) <<
"Beamforming input image...[Done]";
365 if (processSettings.DoCropping)
368 MITK_INFO(input.verbose) <<
"Applying Crop filter to image...";
369 output = m_FilterService->ApplyCropping(output,
370 cropSettings.above, cropSettings.below, cropSettings.right, cropSettings.left, cropSettings.zStart, cropSettings.zEnd, &err);
371 MITK_INFO(input.verbose) <<
"Applying Crop filter to image...[Done]";
373 if (processSettings.DoBmode)
375 MITK_INFO(input.verbose) <<
"Applying BModeFilter to image...";
376 output = m_FilterService->ApplyBmodeFilter(output, bmodeSettings.method, bmodeSettings.UseLogFilter);
377 MITK_INFO(input.verbose) <<
"Applying BModeFilter to image...[Done]";
379 if (processSettings.DoResampling)
381 double spacing[3] = { output->GetGeometry()->GetSpacing()[0] * output->GetDimension(0) / resSettings.dimX, resSettings.spacing, output->GetGeometry()->GetSpacing()[2] };
382 MITK_INFO(input.verbose) <<
"Applying Resample filter to image...";
383 output = m_FilterService->ApplyResampling(output, spacing);
384 if (output->GetDimension(0) != resSettings.dimX)
386 double dim[3] = { (double)resSettings.dimX, (
double)output->GetDimension(1), (double)output->GetDimension(2) };
387 output = m_FilterService->ApplyResamplingToDim(output, dim);
389 MITK_INFO(input.verbose) <<
"Applying Resample filter to image...[Done]";
392 MITK_INFO(input.verbose) <<
"Saving image...";
394 MITK_INFO(input.verbose) <<
"Saving image...[Done]";
396 MITK_INFO(input.verbose) <<
"Beamforming input image...[Done]";
void setContributor(std::string contributor)
ValueType * any_cast(Any *operand)
void addArgument(const std::string &longarg, const std::string &shortarg, Type type, const std::string &argLabel, const std::string &argHelp=std::string(), const us::Any &defaultValue=us::Any(), bool optional=true, bool ignoreRest=false, bool deprecated=false, mitkCommandLineParser::Channel channel=mitkCommandLineParser::Channel::None)
std::map< std::string, us::Any > parseArguments(const StringContainerType &arguments, bool *ok=nullptr)
std::string outputFilename
An object of this class represents an exception of MITK. Please don't instantiate exceptions manually...
bool compare(std::pair< double, int > i, std::pair< double, int > j)
void setCategory(std::string category)
void setArgumentPrefix(const std::string &longPrefix, const std::string &shortPrefix)
static void Save(const mitk::BaseData *data, const std::string &path, bool setPathProperty=false)
Save a mitk::BaseData instance.
void setTitle(std::string title)
void setDescription(std::string description)
BModeMethod
Defines the methods for the B-Mode filter Currently implemented are an Envelope Detection filter and ...
void beginGroup(const std::string &description)