2 #include <tclap/CmdLine.h> 4 #include <itkImageFileReader.h> 5 #include <itkImageFileWriter.h> 8 #include <itkTimeProbe.h> 10 #include <boost/lexical_cast.hpp> 11 #include <boost/algorithm/string.hpp> 13 #include <itkCommand.h> 16 void eventCallback (itk::Object* caller,
const itk::EventObject& event,
void* clientData)
18 itk::ProcessObject * processObject = (itk::ProcessObject*) caller;
19 std::cout<<
"\033[K\rProgression: "<<(int)(processObject->GetProgress() * 100)<<
"%"<<std::flush;
22 int main(
int argc,
char **argv)
24 TCLAP::CmdLine cmd(
"INRIA / IRISA - VisAGeS/Empenn Team",
' ',ANIMA_VERSION);
26 TCLAP::ValueArg<std::string> t2Arg(
"l",
"t2",
"List of T2 relaxometry images",
true,
"",
"T2 relaxometry images",cmd);
27 TCLAP::ValueArg<std::string> maskArg(
"m",
"maskname",
"Computation mask",
false,
"",
"computation mask",cmd);
29 TCLAP::ValueArg<std::string> t1MapArg(
"",
"t1",
"T1 map",
false,
"",
"T1 map",cmd);
31 TCLAP::ValueArg<std::string> resT2Arg(
"O",
"out-t2",
"Result T2 image",
false,
"",
"result T2 image",cmd);
32 TCLAP::ValueArg<std::string> resM0Arg(
"",
"out-m0",
"Result M0 image",
false,
"",
"result M0 image",cmd);
33 TCLAP::ValueArg<std::string> resMWFArg(
"o",
"out-mwf",
"Result MWF image",
true,
"",
"result MWF image",cmd);
34 TCLAP::ValueArg<std::string> resB1Arg(
"",
"out-b1",
"Result B1 image",
false,
"",
"result B1 image",cmd);
35 TCLAP::ValueArg<std::string> resCostArg(
"c",
"out-cost",
"Result cost image",
false,
"",
"result cost image",cmd);
37 TCLAP::ValueArg<double> echoSpacingArg(
"e",
"echo-spacing",
"Spacing between two successive echoes (default: 10)",
false,10,
"Spacing between echoes",cmd);
38 TCLAP::ValueArg<double> excitationT2FlipAngleArg(
"",
"t2-ex-flip",
"Excitation flip angle for T2 (in degrees, default: 90)",
false,90,
"T2 excitation flip angle",cmd);
39 TCLAP::ValueArg<double> t2FlipAngleArg(
"",
"t2-flip",
"All flip angles for T2 (in degrees, default: 180)",
false,180,
"T2 flip angle",cmd);
40 TCLAP::ValueArg<double> backgroundSignalThresholdArg(
"t",
"signal-thr",
"Background signal threshold (default: 10)",
false,10,
"Background signal threshold",cmd);
41 TCLAP::ValueArg<double> regulIntensityArg(
"r",
"reg-int",
"Tikhonov regularization intensity (default: 1.08)",
false,1.08,
"regularization intensity",cmd);
42 TCLAP::ValueArg<double> nlRegulIntensityArg(
"",
"nl-reg-int",
"Tikhonov regularization intensity in NL mode (default: 1.5)",
false,1.5,
"regularization intensity",cmd);
44 TCLAP::ValueArg<double> myelinThrArg(
"",
"mye-thr",
"T2 myelin threshold for MWF computation (default: 50)",
false,50,
"T2 myelin threshold",cmd);
45 TCLAP::ValueArg<unsigned int> numT2CompartmentsArg(
"n",
"num-t2",
"Number of T2 compartments (default: 40)",
false,40,
"Number of T2 compartments",cmd);
46 TCLAP::ValueArg<double> t2LowerBoundArg(
"",
"low-t2",
"Lower T2 value (default: 15)",
false,15,
"T2 lower value",cmd);
47 TCLAP::ValueArg<double> t2UpperBoundArg(
"",
"up-t2",
"Upper T2 value (default: 2000)",
false,2000,
"T2 upper value",cmd);
49 TCLAP::ValueArg<unsigned int> b1NumOptimizerIterArg(
"",
"b1-opt-iter",
"Maximal number of optimizer iterations (default: 200)",
false,200,
"Maximal number of optimizer iterations",cmd);
50 TCLAP::ValueArg<double> b1OptimizerStopConditionArg(
"",
"b1-opt-stop",
"Optimizer stopping threshold (default: 1.0e-4)",
false,1.0e-4,
"B1 Optimizer stopping threshold",cmd);
51 TCLAP::ValueArg<double> b1OptimizerInitialStepArg(
"i",
"b1-opt-init",
"Optimizer initial step (default: 0.1)",
false,0.1,
"B1 Optimizer initial step",cmd);
52 TCLAP::ValueArg<double> b1ToleranceArg(
"",
"b1-tol",
"B1 tolerance threshold of convergence (default: 1.0e-4)",
false,1.0e-4,
"B1 tolerance for optimization convergence",cmd);
55 TCLAP::SwitchArg nlEstimationArg(
"N",
"nl-est",
"NL estimation of MWF",cmd,
false);
56 TCLAP::ValueArg<double> weightThrArg(
"w",
"weightThr",
"Weight threshold: patches around have to be similar enough -> default: 0.0",
false,0.0,
"Weight threshold",cmd);
57 TCLAP::ValueArg<double> betaArg(
"b",
"beta",
"Beta parameter for local noise estimation -> default: 1",
false,1,
"Beta for local noise estimation",cmd);
58 TCLAP::ValueArg<double> meanMinArg(
"",
"meanMin",
"Minimun mean threshold (default: 0.95)",
false,0.95,
"Minimun mean threshold",cmd);
59 TCLAP::ValueArg<double> varMinArg(
"v",
"varMin",
"Minimun variance threshold -> default: 0.5",
false,0.5,
"Minimun variance threshold",cmd);
60 TCLAP::ValueArg<unsigned int> patchHSArg(
"S",
"patchHalfSize",
"Patch half size in each direction -> default: 1",
false,1,
"patch half size",cmd);
61 TCLAP::ValueArg<unsigned int> patchSSArg(
"s",
"patchStepSize",
"Patch step size for searching -> default: 1",
false,1,
"Patch search step size",cmd);
62 TCLAP::ValueArg<unsigned int> patchNeighArg(
"",
"patchNeighborhood",
"Patch half neighborhood size -> default: 5",
false,5,
"Patch search neighborhood size",cmd);
64 TCLAP::ValueArg<unsigned int> nbpArg(
"T",
"numberofthreads",
"Number of threads to run on (default : all cores)",
false,itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads(),
"number of threads",cmd);
70 catch (TCLAP::ArgException& e)
72 std::cerr <<
"Error: " << e.error() <<
"for argument " << e.argId() << std::endl;
76 typedef itk::Image <double,3> InputImageType;
77 typedef InputImageType OutputImageType;
79 typedef FilterType::OutputImageType OutputImageType;
80 typedef FilterType::VectorOutputImageType VectorOutputImageType;
81 typedef itk::ImageFileReader <InputImageType> InputImageReaderType;
83 FilterType::Pointer mainFilter = FilterType::New();
85 unsigned int numInputs = anima::setMultipleImageFilterInputsFromFileName<InputImageType,FilterType>(t2Arg.getValue(),mainFilter);
87 mainFilter->SetEchoSpacing(echoSpacingArg.getValue());
88 mainFilter->SetT2FlipAngles(t2FlipAngleArg.getValue() * M_PI / 180.0,numInputs);
89 mainFilter->SetT2ExcitationFlipAngle(excitationT2FlipAngleArg.getValue() * M_PI / 180.0);
90 mainFilter->SetB1MaximumOptimizerIterations(b1NumOptimizerIterArg.getValue());
91 mainFilter->SetB1OptimizerStopCondition(b1OptimizerStopConditionArg.getValue());
92 mainFilter->SetB1OptimizerInitialStep(b1OptimizerInitialStepArg.getValue());
93 mainFilter->SetB1Tolerance(b1ToleranceArg.getValue());
95 mainFilter->SetLowerT2Bound(t2LowerBoundArg.getValue());
96 mainFilter->SetUpperT2Bound(t2UpperBoundArg.getValue());
97 mainFilter->SetMyelinThreshold(myelinThrArg.getValue());
98 mainFilter->SetNumberOfT2Compartments(numT2CompartmentsArg.getValue());
99 mainFilter->SetRegularizationIntensity(regulIntensityArg.getValue());
100 mainFilter->SetNLEstimation(
false);
102 if (t1MapArg.getValue() !=
"")
104 InputImageReaderType::Pointer t1MapRead = InputImageReaderType::New();
105 t1MapRead->SetFileName(t1MapArg.getValue().c_str());
108 mainFilter->SetT1Map(t1MapRead->GetOutput());
111 if (maskArg.getValue() !=
"")
113 typedef itk::ImageFileReader < itk::Image <unsigned char, 3> > itkMaskReader;
114 itkMaskReader::Pointer maskRead = itkMaskReader::New();
115 maskRead->SetFileName(maskArg.getValue().c_str());
118 mainFilter->SetComputationMask(maskRead->GetOutput());
121 mainFilter->SetAverageSignalThreshold(backgroundSignalThresholdArg.getValue());
122 mainFilter->SetNumberOfWorkUnits(nbpArg.getValue());
124 itk::CStyleCommand::Pointer callback = itk::CStyleCommand::New();
126 mainFilter->AddObserver(itk::ProgressEvent(), callback );
128 itk::TimeProbe tmpTime;
133 mainFilter->Update();
135 catch (itk::ExceptionObject &e)
137 std::cerr << e << std::endl;
142 std::cout <<
"Regular estimation computation time: " << tmpTime.GetTotal() << std::endl;
144 FilterType::OutputImagePointer outMWFImage = mainFilter->GetMWFOutputImage();
145 outMWFImage->DisconnectPipeline();
146 FilterType::OutputImagePointer outM0Image = mainFilter->GetM0OutputImage();
147 outM0Image->DisconnectPipeline();
148 FilterType::OutputImagePointer outCostImage = mainFilter->GetCostOutputImage();
149 outCostImage->DisconnectPipeline();
150 FilterType::OutputImagePointer outB1Image = mainFilter->GetB1OutputImage();
151 outB1Image->DisconnectPipeline();
152 FilterType::VectorOutputImagePointer outT2Image = mainFilter->GetT2OutputImage();
153 outT2Image->DisconnectPipeline();
155 if (nlEstimationArg.isSet())
157 FilterType::Pointer secondaryFilter = FilterType::New();
158 for (
unsigned int i = 0;i < mainFilter->GetNumberOfIndexedInputs();++i)
159 secondaryFilter->SetInput(i,mainFilter->GetInput(i));
161 secondaryFilter->SetEchoSpacing(echoSpacingArg.getValue());
162 secondaryFilter->SetT2FlipAngles(t2FlipAngleArg.getValue() * M_PI / 180.0,numInputs);
163 secondaryFilter->SetT2ExcitationFlipAngle(excitationT2FlipAngleArg.getValue() * M_PI / 180.0);
164 secondaryFilter->SetB1MaximumOptimizerIterations(b1NumOptimizerIterArg.getValue());
165 secondaryFilter->SetB1OptimizerStopCondition(b1OptimizerStopConditionArg.getValue());
166 secondaryFilter->SetB1OptimizerInitialStep(b1OptimizerInitialStepArg.getValue());
167 secondaryFilter->SetB1Tolerance(b1ToleranceArg.getValue());
169 secondaryFilter->SetLowerT2Bound(t2LowerBoundArg.getValue());
170 secondaryFilter->SetUpperT2Bound(t2UpperBoundArg.getValue());
171 secondaryFilter->SetMyelinThreshold(myelinThrArg.getValue());
172 secondaryFilter->SetNumberOfT2Compartments(numT2CompartmentsArg.getValue());
173 secondaryFilter->SetRegularizationIntensity(nlRegulIntensityArg.getValue());
175 secondaryFilter->SetT1Map(mainFilter->GetT1Map());
176 secondaryFilter->SetComputationMask(mainFilter->GetComputationMask());
178 secondaryFilter->SetAverageSignalThreshold(backgroundSignalThresholdArg.getValue());
179 secondaryFilter->SetNumberOfWorkUnits(nbpArg.getValue());
181 itk::CStyleCommand::Pointer secondaryCallback = itk::CStyleCommand::New();
183 secondaryFilter->AddObserver(itk::ProgressEvent(), secondaryCallback);
185 secondaryFilter->SetNLEstimation(
true);
186 secondaryFilter->SetWeightThreshold(weightThrArg.getValue());
187 secondaryFilter->SetBetaParameter(betaArg.getValue());
188 secondaryFilter->SetMeanMinThreshold(meanMinArg.getValue());
189 secondaryFilter->SetVarMinThreshold(varMinArg.getValue());
190 secondaryFilter->SetPatchHalfSize(patchHSArg.getValue());
191 secondaryFilter->SetSearchStepSize(patchSSArg.getValue());
192 secondaryFilter->SetSearchNeighborhood(patchNeighArg.getValue());
194 secondaryFilter->SetInitialB1Map(outB1Image);
195 secondaryFilter->SetInitialT2Map(outT2Image);
196 secondaryFilter->SetInitialM0Map(outM0Image);
198 itk::TimeProbe tmpTimeNL;
203 secondaryFilter->Update();
205 catch (itk::ExceptionObject &e)
207 std::cerr << e << std::endl;
212 std::cout <<
"NL estimation computation time: " << tmpTimeNL.GetTotal() << std::endl;
214 outMWFImage = secondaryFilter->GetMWFOutputImage();
215 outMWFImage->DisconnectPipeline();
216 outM0Image = secondaryFilter->GetM0OutputImage();
217 outM0Image->DisconnectPipeline();
218 outCostImage = secondaryFilter->GetCostOutputImage();
219 outCostImage->DisconnectPipeline();
220 outB1Image = secondaryFilter->GetB1OutputImage();
221 outB1Image->DisconnectPipeline();
222 outT2Image = secondaryFilter->GetT2OutputImage();
223 outT2Image->DisconnectPipeline();
226 anima::writeImage<OutputImageType> (resMWFArg.getValue(),outMWFImage);
228 if (resT2Arg.getValue() !=
"")
229 anima::writeImage<VectorOutputImageType> (resT2Arg.getValue(),outT2Image);
231 if (resM0Arg.getValue() !=
"")
232 anima::writeImage<OutputImageType> (resM0Arg.getValue(),outM0Image);
234 if (resB1Arg.getValue() !=
"")
235 anima::writeImage<OutputImageType> (resB1Arg.getValue(),outB1Image);
237 if (resCostArg.getValue() !=
"")
238 anima::writeImage<OutputImageType> (resCostArg.getValue(),outCostImage);
int main(int argc, char **argv)
Implements multi-peak T2 relaxometry estimation (with or without regularization)
void eventCallback(itk::Object *caller, const itk::EventObject &event, void *clientData)