18 #include <boost/progress.hpp>
19 #include <vtkSmartPointer.h>
20 #include <vtkPolyData.h>
21 #include <vtkCellArray.h>
22 #include <vtkPoints.h>
23 #include <vtkPolyLine.h>
24 #include <itkImageRegionIteratorWithIndex.h>
25 #include <itkResampleImageFilter.h>
26 #include <itkNearestNeighborInterpolateImageFunction.h>
27 #include <itkBSplineInterpolateImageFunction.h>
28 #include <itkCastImageFilter.h>
29 #include <itkImageFileWriter.h>
30 #include <itkRescaleIntensityImageFilter.h>
31 #include <itkWindowedSincInterpolateImageFunction.h>
35 #include <itkAddImageFilter.h>
36 #include <itkConstantPadImageFilter.h>
37 #include <itkCropImageFilter.h>
39 #include <vtkTransform.h>
43 #include <itkImageDuplicator.h>
44 #include <itksys/SystemTools.hxx>
46 #include <itkDiffusionTensor3DReconstructionImageFilter.h>
47 #include <itkDiffusionTensor3D.h>
49 #include <boost/lexical_cast.hpp>
51 #include <itkInvertIntensityImageFilter.h>
52 #include <itkShiftScaleImageFilter.h>
53 #include <itkExtractImageFilter.h>
55 #include <boost/algorithm/string/replace.hpp>
60 template<
class PixelType >
64 , m_UseConstantRandSeed(false)
65 , m_RandGen(
itk::Statistics::MersenneTwisterRandomVariateGenerator::
New())
70 template<
class PixelType >
76 template<
class PixelType >
80 int numFiberCompartments = m_Parameters.m_FiberModelList.size();
82 ImageRegion<2> sliceRegion;
83 sliceRegion.SetSize(0, m_WorkingImageRegion.GetSize()[0]);
84 sliceRegion.SetSize(1, m_WorkingImageRegion.GetSize()[1]);
86 sliceSpacing[0] = m_WorkingSpacing[0];
87 sliceSpacing[1] = m_WorkingSpacing[1];
91 magnitudeDwiImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing );
92 magnitudeDwiImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin );
93 magnitudeDwiImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
94 magnitudeDwiImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
95 magnitudeDwiImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
96 magnitudeDwiImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
97 magnitudeDwiImage->SetVectorLength( images.at(0)->GetVectorLength() );
98 magnitudeDwiImage->Allocate();
99 magnitudeDwiImage->FillBuffer(nullPix);
102 m_PhaseImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing );
103 m_PhaseImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin );
104 m_PhaseImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
105 m_PhaseImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
106 m_PhaseImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
107 m_PhaseImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
108 m_PhaseImage->SetVectorLength( images.at(0)->GetVectorLength() );
109 m_PhaseImage->Allocate();
110 m_PhaseImage->FillBuffer(nullPix);
113 m_KspaceImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing );
114 m_KspaceImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin );
115 m_KspaceImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
116 m_KspaceImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
117 m_KspaceImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
118 m_KspaceImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
119 m_KspaceImage->SetVectorLength( m_Parameters.m_SignalGen.m_NumberOfCoils );
120 m_KspaceImage->Allocate();
121 m_KspaceImage->FillBuffer(nullPix);
123 std::vector< unsigned int > spikeVolume;
124 for (
unsigned int i=0; i<m_Parameters.m_SignalGen.m_Spikes; i++)
125 spikeVolume.push_back(m_RandGen->GetIntegerVariate()%(images.at(0)->GetVectorLength()));
126 std::sort (spikeVolume.begin(), spikeVolume.end());
127 std::reverse (spikeVolume.begin(), spikeVolume.end());
130 double a = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0)*m_Parameters.m_SignalGen.m_ImageSpacing[0];
131 double b = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)*m_Parameters.m_SignalGen.m_ImageSpacing[1];
132 double c = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(2)*m_Parameters.m_SignalGen.m_ImageSpacing[2];
133 double diagonal = sqrt(a*a+b*b)/1000;
136 std::vector< itk::Vector<double, 3> > coilPositions;
137 itk::Vector<double, 3> pos; pos.Fill(0.0); pos[1] = -diagonal/2;
138 itk::Vector<double, 3> center;
139 center[0] = a/2-m_Parameters.m_SignalGen.m_ImageSpacing[0]/2;
140 center[1] = b/2-m_Parameters.m_SignalGen.m_ImageSpacing[2]/2;
141 center[2] = c/2-m_Parameters.m_SignalGen.m_ImageSpacing[1]/2;
142 for (
int c=0; c<m_Parameters.m_SignalGen.m_NumberOfCoils; c++)
144 coilPositions.push_back(pos);
145 m_CoilPointset->InsertPoint(c, pos*1000 + m_Parameters.m_SignalGen.m_ImageOrigin.GetVectorFromOrigin() + center );
147 double rz = 360.0/m_Parameters.m_SignalGen.m_NumberOfCoils *
M_PI/180;
148 vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity();
149 rotZ[0][0] = cos(rz);
150 rotZ[1][1] = rotZ[0][0];
151 rotZ[0][1] = -sin(rz);
152 rotZ[1][0] = -rotZ[0][1];
154 pos.SetVnlVector(rotZ*pos.GetVnlVector());
157 PrintToLog(
"0% 10 20 30 40 50 60 70 80 90 100%",
false,
true,
false);
158 PrintToLog(
"|----|----|----|----|----|----|----|----|----|----|\n*",
false,
false,
false);
159 unsigned long lastTick = 0;
161 boost::progress_display disp(images.at(0)->GetVectorLength()*images.at(0)->GetLargestPossibleRegion().GetSize(2));
162 for (
unsigned int g=0; g<images.at(0)->GetVectorLength(); g++)
164 std::vector< unsigned int > spikeSlice;
165 while (!spikeVolume.empty() && spikeVolume.back()==g)
167 spikeSlice.push_back(m_RandGen->GetIntegerVariate()%images.at(0)->GetLargestPossibleRegion().GetSize(2));
168 spikeVolume.pop_back();
170 std::sort (spikeSlice.begin(), spikeSlice.end());
171 std::reverse (spikeSlice.begin(), spikeSlice.end());
173 for (
unsigned int z=0; z<images.at(0)->GetLargestPossibleRegion().GetSize(2); z++)
175 std::vector< SliceType::Pointer > compartmentSlices;
176 std::vector< double > t2Vector;
177 std::vector< double > t1Vector;
179 for (
unsigned int i=0; i<images.size(); i++)
182 if (i<numFiberCompartments)
183 signalModel = m_Parameters.m_FiberModelList.at(i);
185 signalModel = m_Parameters.m_NonFiberModelList.at(i-numFiberCompartments);
188 slice->SetLargestPossibleRegion( sliceRegion );
189 slice->SetBufferedRegion( sliceRegion );
190 slice->SetRequestedRegion( sliceRegion );
191 slice->SetSpacing(sliceSpacing);
193 slice->FillBuffer(0.0);
196 for (
unsigned int y=0; y<images.at(0)->GetLargestPossibleRegion().GetSize(1); y++)
197 for (
unsigned int x=0; x<images.at(0)->GetLargestPossibleRegion().GetSize(0); x++)
199 SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y;
200 DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z;
202 slice->SetPixel(index2D, images.at(i)->GetPixel(index3D)[g]);
205 compartmentSlices.push_back(slice);
206 t2Vector.push_back(signalModel->
GetT2());
207 t1Vector.push_back(signalModel->
GetT1());
211 while (!spikeSlice.empty() && spikeSlice.back()==z)
214 spikeSlice.pop_back();
216 int spikeCoil = m_RandGen->GetIntegerVariate()%m_Parameters.m_SignalGen.m_NumberOfCoils;
218 if (this->GetAbortGenerateData())
221 #pragma omp parallel for
222 for (
int c=0; c<m_Parameters.m_SignalGen.m_NumberOfCoils; c++)
226 idft->SetCompartmentImages(compartmentSlices);
227 idft->SetT2(t2Vector);
228 idft->SetT1(t1Vector);
229 idft->SetUseConstantRandSeed(m_UseConstantRandSeed);
230 idft->SetParameters(&m_Parameters);
231 idft->SetZ((
double)z-(
double)( images.at(0)->GetLargestPossibleRegion().GetSize(2)
232 -images.at(0)->GetLargestPossibleRegion().GetSize(2)%2 ) / 2.0);
234 idft->SetCoilPosition(coilPositions.at(c));
235 idft->SetFiberBundle(m_FiberBundleWorkingCopy);
236 idft->SetTranslation(m_Translations.at(g));
237 idft->SetRotation(m_Rotations.at(g));
238 idft->SetDiffusionGradientDirection(m_Parameters.m_SignalGen.GetGradientDirection(g));
240 idft->SetSpikesPerSlice(numSpikes);
244 if (c==spikeCoil && numSpikes>0)
246 m_SpikeLog +=
"Volume " + boost::lexical_cast<std::string>(g) +
" Coil " + boost::lexical_cast<std::string>(c) +
"\n";
247 m_SpikeLog += idft->GetSpikeLog();
251 fSlice = idft->GetOutput();
256 dft->SetInput(fSlice);
257 dft->SetParameters(m_Parameters);
259 newSlice = dft->GetOutput();
262 for (
unsigned int y=0; y<fSlice->GetLargestPossibleRegion().GetSize(1); y++)
263 for (
unsigned int x=0; x<fSlice->GetLargestPossibleRegion().GetSize(0); x++)
265 DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z;
266 ComplexSliceType::IndexType index2D; index2D[0]=x; index2D[1]=y;
269 double magn = sqrt(cPix.real()*cPix.real()+cPix.imag()*cPix.imag());
272 phase = atan( cPix.imag()/cPix.real() );
278 if (m_Parameters.m_SignalGen.m_NumberOfCoils>1)
280 dwiPix[g] += magn*magn;
281 phasePix[g] += phase*phase;
291 magnitudeDwiImage->SetPixel(index3D, dwiPix);
292 m_PhaseImage->SetPixel(index3D, phasePix);
298 kspacePix[c] = idft->GetKSpaceImage()->GetPixel(index2D);
299 m_KspaceImage->SetPixel(index3D, kspacePix);
305 if (m_Parameters.m_SignalGen.m_NumberOfCoils>1)
308 #pragma omp parallel for
310 #pragma omp parallel for collapse(2)
312 for (
int y=0; y<magnitudeDwiImage->GetLargestPossibleRegion().GetSize(1); y++)
313 for (
int x=0; x<magnitudeDwiImage->GetLargestPossibleRegion().GetSize(0); x++)
315 DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z;
317 magPix[g] = sqrt(magPix[g]/m_Parameters.m_SignalGen.m_NumberOfCoils);
320 phasePix[g] = sqrt(phasePix[g]/m_Parameters.m_SignalGen.m_NumberOfCoils);
324 magnitudeDwiImage->SetPixel(index3D, magPix);
325 m_PhaseImage->SetPixel(index3D, phasePix);
331 unsigned long newTick = 50*disp.count()/disp.expected_count();
332 for (
unsigned long tick = 0; tick<(newTick-lastTick); tick++)
333 PrintToLog(
"*",
false,
false,
false);
337 PrintToLog(
"\n",
false);
338 return magnitudeDwiImage;
341 template<
class PixelType >
348 itk::ImageRegionIterator< ItkDoubleImgType > it(image, image->GetLargestPossibleRegion());
351 if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull() && m_Parameters.m_SignalGen.m_MaskImage->GetPixel(it.GetIndex())<=0)
367 scaler->SetInput(image);
368 scaler->SetShift(-min);
369 scaler->SetScale(1.0/(max-min));
371 return scaler->GetOutput();
374 template<
class PixelType >
377 m_UseRelativeNonFiberVolumeFractions =
false;
380 int fibVolImages = 0;
381 for (
int i=0; i<m_Parameters.m_FiberModelList.size(); i++)
383 if (m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage().IsNotNull())
385 PrintToLog(
"Using volume fraction map for fiber compartment " + boost::lexical_cast<std::string>(i+1));
391 int nonfibVolImages = 0;
392 for (
int i=0; i<m_Parameters.m_NonFiberModelList.size(); i++)
394 if (m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage().IsNotNull())
396 PrintToLog(
"Using volume fraction map for non-fiber compartment " + boost::lexical_cast<std::string>(i+1));
407 if ( fibVolImages<m_Parameters.m_FiberModelList.size() && nonfibVolImages==1 && m_Parameters.m_NonFiberModelList.size()==2)
409 PrintToLog(
"Calculating missing non-fiber volume fraction image by inverting the other.\n"
410 "Assuming non-fiber volume fraction images to contain values relative to the"
411 " remaining non-fiber volume, not absolute values.");
414 inverter->SetMaximum(1.0);
415 if ( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage().IsNull()
416 && m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage().IsNotNull() )
420 inverter->SetInput( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage() );
422 m_Parameters.m_NonFiberModelList[0]->SetVolumeFractionImage(inverter->GetOutput());
424 else if ( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage().IsNull()
425 && m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage().IsNotNull() )
429 inverter->SetInput( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage() );
431 m_Parameters.m_NonFiberModelList[1]->SetVolumeFractionImage(inverter->GetOutput());
435 itkExceptionMacro(
"Something went wrong in automatically calculating the missing non-fiber volume fraction image!"
436 " Did you use two non fiber compartments but only one volume fraction image?"
437 " Then it should work and this error is really strange.");
439 m_UseRelativeNonFiberVolumeFractions =
true;
445 if (m_Parameters.m_FiberModelList.size()>2
446 && fibVolImages!=m_Parameters.m_FiberModelList.size())
447 itkExceptionMacro(
"More than two fiber compartment selected but no corresponding volume fraction maps set!");
450 if (m_Parameters.m_NonFiberModelList.size()>1
451 && nonfibVolImages!=m_Parameters.m_NonFiberModelList.size())
452 itkExceptionMacro(
"More than one non-fiber compartment selected but no volume fraction maps set!");
454 if (fibVolImages<m_Parameters.m_FiberModelList.size() && nonfibVolImages>0)
456 PrintToLog(
"Not all fiber compartments are using an associated volume fraction image.\n"
457 "Assuming non-fiber volume fraction images to contain values relative to the"
458 " remaining non-fiber volume, not absolute values.");
459 m_UseRelativeNonFiberVolumeFractions =
true;
468 m_VolumeFractions.clear();
469 for (
int i=0; i<m_Parameters.m_FiberModelList.size()+m_Parameters.m_NonFiberModelList.size(); i++)
472 doubleImg->SetSpacing( m_WorkingSpacing );
473 doubleImg->SetOrigin( m_WorkingOrigin );
474 doubleImg->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
475 doubleImg->SetLargestPossibleRegion( m_WorkingImageRegion );
476 doubleImg->SetBufferedRegion( m_WorkingImageRegion );
477 doubleImg->SetRequestedRegion( m_WorkingImageRegion );
478 doubleImg->Allocate();
479 doubleImg->FillBuffer(0);
480 m_VolumeFractions.push_back(doubleImg);
484 template<
class PixelType >
488 m_Translations.clear();
493 m_Parameters.m_SignalGen.m_CroppedRegion = m_Parameters.m_SignalGen.m_ImageRegion;
494 m_Parameters.m_SignalGen.m_CroppedRegion.SetSize( 1, m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1)
495 *m_Parameters.m_SignalGen.m_CroppingFactor);
497 itk::Point<double,3> shiftedOrigin = m_Parameters.m_SignalGen.m_ImageOrigin;
498 shiftedOrigin[1] += (m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)
499 -m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1))*m_Parameters.m_SignalGen.m_ImageSpacing[1]/2;
502 m_OutputImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing );
503 m_OutputImage->SetOrigin( shiftedOrigin );
504 m_OutputImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
505 m_OutputImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
506 m_OutputImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
507 m_OutputImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
508 m_OutputImage->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() );
509 m_OutputImage->Allocate();
511 temp.SetSize(m_Parameters.m_SignalGen.GetNumVolumes());
513 m_OutputImage->FillBuffer(temp);
516 double upsampling = 1;
517 if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging)
519 m_WorkingSpacing = m_Parameters.m_SignalGen.m_ImageSpacing;
520 m_WorkingSpacing[0] /= upsampling;
521 m_WorkingSpacing[1] /= upsampling;
522 m_WorkingImageRegion = m_Parameters.m_SignalGen.m_ImageRegion;
523 m_WorkingImageRegion.SetSize(0, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[0]*upsampling);
524 m_WorkingImageRegion.SetSize(1, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[1]*upsampling);
525 m_WorkingOrigin = m_Parameters.m_SignalGen.m_ImageOrigin;
526 m_WorkingOrigin[0] -= m_Parameters.m_SignalGen.m_ImageSpacing[0]/2;
527 m_WorkingOrigin[0] += m_WorkingSpacing[0]/2;
528 m_WorkingOrigin[1] -= m_Parameters.m_SignalGen.m_ImageSpacing[1]/2;
529 m_WorkingOrigin[1] += m_WorkingSpacing[1]/2;
530 m_WorkingOrigin[2] -= m_Parameters.m_SignalGen.m_ImageSpacing[2]/2;
531 m_WorkingOrigin[2] += m_WorkingSpacing[2]/2;
532 m_VoxelVolume = m_WorkingSpacing[0]*m_WorkingSpacing[1]*m_WorkingSpacing[2];
535 m_CompartmentImages.clear();
536 int numFiberCompartments = m_Parameters.m_FiberModelList.size();
537 int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size();
538 for (
int i=0; i<numFiberCompartments+numNonFiberCompartments; i++)
541 doubleDwi->SetSpacing( m_WorkingSpacing );
542 doubleDwi->SetOrigin( m_WorkingOrigin );
543 doubleDwi->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
544 doubleDwi->SetLargestPossibleRegion( m_WorkingImageRegion );
545 doubleDwi->SetBufferedRegion( m_WorkingImageRegion );
546 doubleDwi->SetRequestedRegion( m_WorkingImageRegion );
547 doubleDwi->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() );
548 doubleDwi->Allocate();
550 pix.SetSize(m_Parameters.m_SignalGen.GetNumVolumes());
552 doubleDwi->FillBuffer(pix);
553 m_CompartmentImages.push_back(doubleDwi);
556 if (m_FiberBundle.IsNull() && m_InputImage.IsNotNull())
558 m_CompartmentImages.clear();
560 m_Parameters.m_SignalGen.m_DoAddMotion =
false;
561 m_Parameters.m_SignalGen.m_DoSimulateRelaxation =
false;
563 PrintToLog(
"Simulating acquisition for input diffusion-weighted image.",
false);
565 caster->SetInput(m_InputImage);
568 if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging)
570 PrintToLog(
"Upsampling input diffusion-weighted image for Gibbs ringing simulation.",
false);
573 resampler->SetInput(caster->GetOutput());
574 itk::Vector< double, 3 > samplingFactor;
575 samplingFactor[0] = upsampling;
576 samplingFactor[1] = upsampling;
577 samplingFactor[2] = 1;
578 resampler->SetSamplingFactor(samplingFactor);
581 m_CompartmentImages.push_back(resampler->GetOutput());
584 m_CompartmentImages.push_back(caster->GetOutput());
586 for (
unsigned int g=0; g<m_Parameters.m_SignalGen.GetNumVolumes(); g++)
588 m_Rotation.Fill(0.0);
589 m_Translation.Fill(0.0);
590 m_Rotations.push_back(m_Rotation);
591 m_Translations.push_back(m_Translation);
596 if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging)
598 if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull())
602 rescaler->SetInput(0,m_Parameters.m_SignalGen.m_MaskImage);
603 rescaler->SetOutputMaximum(100);
604 rescaler->SetOutputMinimum(0);
609 resampler->SetInput(rescaler->GetOutput());
610 resampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_MaskImage);
611 resampler->SetSize(m_WorkingImageRegion.GetSize());
612 resampler->SetOutputSpacing(m_WorkingSpacing);
613 resampler->SetOutputOrigin(m_WorkingOrigin);
615 resampler->SetInterpolator(nn_interpolator);
617 m_Parameters.m_SignalGen.m_MaskImage = resampler->GetOutput();
620 if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull())
623 resampler->SetInput(m_Parameters.m_SignalGen.m_FrequencyMap);
624 resampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_FrequencyMap);
625 resampler->SetSize(m_WorkingImageRegion.GetSize());
626 resampler->SetOutputSpacing(m_WorkingSpacing);
627 resampler->SetOutputOrigin(m_WorkingOrigin);
629 resampler->SetInterpolator(nn_interpolator);
631 m_Parameters.m_SignalGen.m_FrequencyMap = resampler->GetOutput();
635 m_MaskImageSet =
true;
636 if (m_Parameters.m_SignalGen.m_MaskImage.IsNull())
639 PrintToLog(
"No tissue mask set",
false);
641 m_Parameters.m_SignalGen.m_MaskImage->SetSpacing( m_WorkingSpacing );
642 m_Parameters.m_SignalGen.m_MaskImage->SetOrigin( m_WorkingOrigin );
643 m_Parameters.m_SignalGen.m_MaskImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
644 m_Parameters.m_SignalGen.m_MaskImage->SetLargestPossibleRegion( m_WorkingImageRegion );
645 m_Parameters.m_SignalGen.m_MaskImage->SetBufferedRegion( m_WorkingImageRegion );
646 m_Parameters.m_SignalGen.m_MaskImage->SetRequestedRegion( m_WorkingImageRegion );
647 m_Parameters.m_SignalGen.m_MaskImage->Allocate();
648 m_Parameters.m_SignalGen.m_MaskImage->FillBuffer(100);
649 m_MaskImageSet =
false;
653 if (m_Parameters.m_SignalGen.m_MaskImage->GetLargestPossibleRegion()!=m_WorkingImageRegion)
655 itkExceptionMacro(
"Mask image and specified DWI geometry are not matching!");
657 PrintToLog(
"Using tissue mask",
false);
660 if (m_Parameters.m_SignalGen.m_DoAddMotion)
662 if (m_Parameters.m_SignalGen.m_DoRandomizeMotion)
664 PrintToLog(
"Random motion artifacts:",
false);
665 PrintToLog(
"Maximum rotation: +/-" + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_Rotation) +
"°",
false);
666 PrintToLog(
"Maximum translation: +/-" + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_Translation) +
"mm",
false);
670 PrintToLog(
"Linear motion artifacts:",
false);
671 PrintToLog(
"Maximum rotation: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_Rotation) +
"°",
false);
672 PrintToLog(
"Maximum translation: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_Translation) +
"mm",
false);
675 if ( m_Parameters.m_SignalGen.m_MotionVolumes.empty() )
678 m_Parameters.m_SignalGen.m_MotionVolumes.push_back(
false);
681 while ( m_Parameters.m_SignalGen.m_MotionVolumes.size() < m_Parameters.m_SignalGen.GetNumVolumes() )
683 m_Parameters.m_SignalGen.m_MotionVolumes.push_back(
true);
687 while ( m_Parameters.m_SignalGen.m_MotionVolumes.size()<m_Parameters.m_SignalGen.GetNumVolumes() )
689 m_Parameters.m_SignalGen.m_MotionVolumes.push_back(
false);
692 m_NumMotionVolumes = 0;
693 for (
int i=0; i<m_Parameters.m_SignalGen.GetNumVolumes(); i++)
695 if (m_Parameters.m_SignalGen.m_MotionVolumes[i])
697 m_NumMotionVolumes++;
705 duplicator->SetInputImage(m_Parameters.m_SignalGen.m_MaskImage);
706 duplicator->Update();
707 m_TransformedMaskImage = duplicator->GetOutput();
710 ImageRegion<3> upsampledImageRegion = m_WorkingImageRegion;
712 upsampledSpacing[0] /= 4;
713 upsampledSpacing[1] /= 4;
714 upsampledSpacing[2] /= 4;
715 upsampledImageRegion.SetSize(0, m_WorkingImageRegion.GetSize()[0]*4);
716 upsampledImageRegion.SetSize(1, m_WorkingImageRegion.GetSize()[1]*4);
717 upsampledImageRegion.SetSize(2, m_WorkingImageRegion.GetSize()[2]*4);
718 itk::Point<double,3> upsampledOrigin = m_WorkingOrigin;
719 upsampledOrigin[0] -= m_WorkingSpacing[0]/2;
720 upsampledOrigin[0] += upsampledSpacing[0]/2;
721 upsampledOrigin[1] -= m_WorkingSpacing[1]/2;
722 upsampledOrigin[1] += upsampledSpacing[1]/2;
723 upsampledOrigin[2] -= m_WorkingSpacing[2]/2;
724 upsampledOrigin[2] += upsampledSpacing[2]/2;
728 upsampler->SetInput(m_Parameters.m_SignalGen.m_MaskImage);
729 upsampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_MaskImage);
730 upsampler->SetSize(upsampledImageRegion.GetSize());
731 upsampler->SetOutputSpacing(upsampledSpacing);
732 upsampler->SetOutputOrigin(upsampledOrigin);
735 upsampler->SetInterpolator(nn_interpolator);
737 m_UpsampledMaskImage = upsampler->GetOutput();
740 template<
class PixelType >
744 PrintToLog(
"Resampling fibers ...");
745 m_SegmentVolume = 0.0001;
746 float minSpacing = 1;
747 if( m_WorkingSpacing[0]<m_WorkingSpacing[1]
748 && m_WorkingSpacing[0]<m_WorkingSpacing[2])
750 minSpacing = m_WorkingSpacing[0];
752 else if (m_WorkingSpacing[1] < m_WorkingSpacing[2])
754 minSpacing = m_WorkingSpacing[1];
758 minSpacing = m_WorkingSpacing[2];
762 m_FiberBundleWorkingCopy = m_FiberBundle->GetDeepCopy();
763 double volumeAccuracy = 10;
764 m_FiberBundleWorkingCopy->ResampleSpline(minSpacing/volumeAccuracy);
765 m_mmRadius = m_Parameters.m_SignalGen.m_AxonRadius/1000;
767 if (m_mmRadius>0) { m_SegmentVolume =
M_PI*m_mmRadius*m_mmRadius*minSpacing/volumeAccuracy; }
769 m_FiberBundleTransformed = m_FiberBundleWorkingCopy;
773 template<
class PixelType >
776 assert( ! m_Logfile.is_open() );
778 std::string filePath;
779 std::string fileName;
782 if (m_Parameters.m_Misc.m_OutputPath.size() > 0)
784 filePath = m_Parameters.m_Misc.m_OutputPath;
785 if( *(--(filePath.cend())) !=
'/')
787 filePath.push_back(
'/');
795 if( itksys::SystemTools::FileIsDirectory( filePath ) )
797 while( *(--(filePath.cend())) ==
'/')
801 filePath = filePath +
'/';
809 if( ! m_Parameters.m_Misc.m_ResultNode->GetName().empty() )
811 fileName = m_Parameters.m_Misc.m_ResultNode->GetName();
818 if( ! m_Parameters.m_Misc.m_OutputPrefix.empty() )
820 fileName = m_Parameters.m_Misc.m_OutputPrefix + fileName;
824 fileName =
"fiberfox";
828 std::string NameTest = fileName;
830 while( itksys::SystemTools::FileExists( filePath +
'/' + fileName +
".log" )
833 fileName = NameTest +
"_" + boost::lexical_cast<std::string>(c);
839 m_Logfile.open( ( filePath +
'/' + fileName +
".log" ).c_str() );
841 catch (
const std::ios_base::failure &fail)
843 MITK_ERROR <<
"itkTractsToDWIImageFilter.cpp: Exception " << fail.what()
844 <<
" while trying to open file" << filePath <<
'/' << fileName <<
".log";
848 if ( m_Logfile.is_open() )
850 PrintToLog(
"Logfile: " + filePath +
'/' + fileName +
".log",
false );
855 m_StatusText +=
"Logfile could not be opened!\n";
856 MITK_ERROR <<
"itkTractsToDWIImageFilter.cpp: Logfile could not be opened!";
862 template<
class PixelType >
866 if ( ! PrepareLogFile() )
868 this->SetAbortGenerateData(
true );
875 if (m_FiberBundle.IsNull() && m_InputImage.IsNull())
876 itkExceptionMacro(
"Input fiber bundle and input diffusion-weighted image is NULL!");
878 if (m_Parameters.m_FiberModelList.empty() && m_InputImage.IsNull())
879 itkExceptionMacro(
"No diffusion model for fiber compartments defined and input diffusion-weighted"
880 " image is NULL! At least one fiber compartment is necessary to simulate diffusion.");
882 if (m_Parameters.m_NonFiberModelList.empty() && m_InputImage.IsNull())
883 itkExceptionMacro(
"No diffusion model for non-fiber compartments defined and input diffusion-weighted"
884 " image is NULL! At least one non-fiber compartment is necessary to simulate diffusion.");
886 int baselineIndex = m_Parameters.m_SignalGen.GetFirstBaselineIndex();
887 if (baselineIndex<0) { itkExceptionMacro(
"No baseline index found!"); }
889 if (!m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition)
891 m_Parameters.m_SignalGen.m_DoAddGibbsRinging =
false;
894 if (m_UseConstantRandSeed)
895 { m_RandGen->SetSeed(0); }
896 else { m_RandGen->SetSeed(); }
899 if ( m_FiberBundle.IsNotNull() )
901 CheckVolumeFractionImages();
902 InitializeFiberData();
904 int numFiberCompartments = m_Parameters.m_FiberModelList.size();
905 int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size();
907 double maxVolume = 0;
908 unsigned long lastTick = 0;
909 int signalModelSeed = m_RandGen->GetIntegerVariate();
911 PrintToLog(
"\n",
false,
false);
912 PrintToLog(
"Generating " + boost::lexical_cast<std::string>(numFiberCompartments+numNonFiberCompartments)
913 +
"-compartment diffusion-weighted signal.");
915 int numFibers = m_FiberBundleWorkingCopy->GetNumFibers();
916 boost::progress_display disp(numFibers*m_Parameters.m_SignalGen.GetNumVolumes());
918 PrintToLog(
"0% 10 20 30 40 50 60 70 80 90 100%",
false,
true,
false);
919 PrintToLog(
"|----|----|----|----|----|----|----|----|----|----|\n*",
false,
false,
false);
921 for (
unsigned int g=0; g<m_Parameters.m_SignalGen.GetNumVolumes(); g++)
927 for (
int i=0; i<m_Parameters.m_FiberModelList.size(); i++)
928 m_Parameters.m_FiberModelList.at(i)->SetSeed(signalModelSeed);
929 for (
int i=0; i<m_Parameters.m_NonFiberModelList.size(); i++)
930 m_Parameters.m_NonFiberModelList.at(i)->SetSeed(signalModelSeed);
934 intraAxonalVolumeImage->SetSpacing( m_WorkingSpacing );
935 intraAxonalVolumeImage->SetOrigin( m_WorkingOrigin );
936 intraAxonalVolumeImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
937 intraAxonalVolumeImage->SetLargestPossibleRegion( m_WorkingImageRegion );
938 intraAxonalVolumeImage->SetBufferedRegion( m_WorkingImageRegion );
939 intraAxonalVolumeImage->SetRequestedRegion( m_WorkingImageRegion );
940 intraAxonalVolumeImage->Allocate();
941 intraAxonalVolumeImage->FillBuffer(0);
944 vtkPolyData* fiberPolyData = m_FiberBundleTransformed->GetFiberPolyData();
946 if (!m_Parameters.m_FiberModelList.empty())
947 for(
int i=0; i<numFibers; i++ )
949 float fiberWeight = m_FiberBundleTransformed->GetFiberWeight(i);
950 vtkCell* cell = fiberPolyData->GetCell(i);
951 int numPoints = cell->GetNumberOfPoints();
952 vtkPoints* points = cell->GetPoints();
957 for(
int j=0; j<numPoints; j++)
959 if (this->GetAbortGenerateData())
961 PrintToLog(
"\n",
false,
false);
962 PrintToLog(
"Simulation aborted");
966 double* temp = points->GetPoint(j);
967 itk::Point<float, 3> vertex = GetItkPoint(temp);
968 itk::Vector<double> v = GetItkVector(temp);
970 itk::Vector<double, 3> dir(3);
971 if (j<numPoints-1) { dir = GetItkVector(points->GetPoint(j+1))-v; }
972 else { dir = v-GetItkVector(points->GetPoint(j-1)); }
974 if ( dir.GetSquaredNorm()<0.0001 || dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2] )
980 itk::ContinuousIndex<float, 3> contIndex;
981 m_TransformedMaskImage->TransformPhysicalPointToIndex(vertex, idx);
982 m_TransformedMaskImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex);
984 if (!m_TransformedMaskImage->GetLargestPossibleRegion().IsInside(idx) || m_TransformedMaskImage->GetPixel(idx)<=0)
990 for (
int k=0; k<numFiberCompartments; k++)
992 m_Parameters.m_FiberModelList[k]->SetFiberDirection(dir);
994 pix[g] += fiberWeight*m_SegmentVolume*m_Parameters.m_FiberModelList[k]->SimulateMeasurement(g);
996 m_CompartmentImages.at(k)->SetPixel(idx, pix);
1000 double vol = intraAxonalVolumeImage->GetPixel(idx) + m_SegmentVolume*fiberWeight;
1001 intraAxonalVolumeImage->SetPixel(idx, vol);
1004 if (vol>maxVolume) { maxVolume = vol; }
1009 unsigned long newTick = 50*disp.count()/disp.expected_count();
1010 for (
unsigned int tick = 0; tick<(newTick-lastTick); tick++)
1012 PrintToLog(
"*",
false,
false,
false);
1018 ImageRegionIterator<ItkUcharImgType> it3(m_TransformedMaskImage, m_TransformedMaskImage->GetLargestPossibleRegion());
1020 if (m_Parameters.m_SignalGen.m_AxonRadius<0.0001 || maxVolume>m_VoxelVolume)
1021 fact = m_VoxelVolume/maxVolume;
1022 while(!it3.IsAtEnd())
1026 DoubleDwiType::IndexType index = it3.GetIndex();
1027 itk::Point<double, 3> point;
1028 m_TransformedMaskImage->TransformIndexToPhysicalPoint(index, point);
1029 if ( m_Parameters.m_SignalGen.m_DoAddMotion && g>=0
1030 && m_Parameters.m_SignalGen.m_MotionVolumes[g] )
1032 if (m_Parameters.m_SignalGen.m_DoRandomizeMotion)
1034 point = m_FiberBundleWorkingCopy->TransformPoint( point.GetVnlVector(), -m_Rotation[0], -m_Rotation[1], -m_Rotation[2],
1035 -m_Translation[0], -m_Translation[1], -m_Translation[2] );
1039 point = m_FiberBundleWorkingCopy->TransformPoint( point.GetVnlVector(),
1040 -m_Rotation[0]*m_MotionCounter, -m_Rotation[1]*m_MotionCounter, -m_Rotation[2]*m_MotionCounter,
1041 -m_Translation[0]*m_MotionCounter, -m_Translation[1]*m_MotionCounter, -m_Translation[2]*m_MotionCounter );
1045 double iAxVolume = intraAxonalVolumeImage->GetPixel(index);
1048 double fact2 = fact;
1049 if ( m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()!=
nullptr
1050 && iAxVolume>0.0001 )
1052 double val = InterpolateValue(point, m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage());
1053 if (val>=0) { fact2 = m_VoxelVolume*val/iAxVolume; }
1057 for (
int i=0; i<numFiberCompartments; i++)
1061 m_CompartmentImages.at(i)->SetPixel(index, pix);
1065 SimulateExtraAxonalSignal(index, iAxVolume*fact2, g);
1071 PrintToLog(
"\n",
false);
1072 if (this->GetAbortGenerateData())
1074 PrintToLog(
"\n",
false,
false);
1075 PrintToLog(
"Simulation aborted");
1081 double signalScale = m_Parameters.m_SignalGen.m_SignalScale;
1082 if ( m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition )
1084 PrintToLog(
"\n",
false,
false);
1085 PrintToLog(
"Simulating k-space acquisition using "
1086 +boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_NumberOfCoils)
1089 switch (m_Parameters.m_SignalGen.m_AcquisitionType)
1091 case SignalGenerationParameters::SingleShotEpi:
1093 PrintToLog(
"Acquisition type: single shot EPI",
false);
1096 case SignalGenerationParameters::SpinEcho:
1098 PrintToLog(
"Acquisition type: classic spin echo with cartesian k-space trajectory",
false);
1103 PrintToLog(
"Acquisition type: single shot EPI",
false);
1108 if (m_Parameters.m_SignalGen.m_NoiseVariance>0)
1109 PrintToLog(
"Simulating complex Gaussian noise",
false);
1110 if (m_Parameters.m_SignalGen.m_DoSimulateRelaxation)
1111 PrintToLog(
"Simulating signal relaxation",
false);
1112 if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull())
1113 PrintToLog(
"Simulating distortions",
false);
1114 if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging)
1115 PrintToLog(
"Simulating ringing artifacts",
false);
1116 if (m_Parameters.m_SignalGen.m_EddyStrength>0)
1117 PrintToLog(
"Simulating eddy currents",
false);
1118 if (m_Parameters.m_SignalGen.m_Spikes>0)
1119 PrintToLog(
"Simulating spikes",
false);
1120 if (m_Parameters.m_SignalGen.m_CroppingFactor<1.0)
1121 PrintToLog(
"Simulating aliasing artifacts",
false);
1122 if (m_Parameters.m_SignalGen.m_KspaceLineOffset>0)
1123 PrintToLog(
"Simulating ghosts",
false);
1125 doubleOutImage = SimulateKspaceAcquisition(m_CompartmentImages);
1130 PrintToLog(
"Summing compartments");
1131 doubleOutImage = m_CompartmentImages.at(0);
1133 for (
unsigned int i=1; i<m_CompartmentImages.size(); i++)
1136 adder->SetInput1(doubleOutImage);
1137 adder->SetInput2(m_CompartmentImages.at(i));
1139 doubleOutImage = adder->GetOutput();
1142 if (this->GetAbortGenerateData())
1144 PrintToLog(
"\n",
false,
false);
1145 PrintToLog(
"Simulation aborted");
1149 PrintToLog(
"Finalizing image");
1151 PrintToLog(
" Scaling signal",
false);
1152 if (m_Parameters.m_NoiseModel)
1153 PrintToLog(
" Adding noise",
false);
1154 unsigned int window = 0;
1156 ImageRegionIterator<OutputImageType> it4 (m_OutputImage, m_OutputImage->GetLargestPossibleRegion());
1158 boost::progress_display disp2(m_OutputImage->GetLargestPossibleRegion().GetNumberOfPixels());
1160 PrintToLog(
"0% 10 20 30 40 50 60 70 80 90 100%",
false,
true,
false);
1161 PrintToLog(
"|----|----|----|----|----|----|----|----|----|----|\n*",
false,
false,
false);
1164 while(!it4.IsAtEnd())
1166 if (this->GetAbortGenerateData())
1168 PrintToLog(
"\n",
false,
false);
1169 PrintToLog(
"Simulation aborted");
1174 unsigned long newTick = 50*disp2.count()/disp2.expected_count();
1175 for (
unsigned long tick = 0; tick<(newTick-lastTick); tick++)
1176 PrintToLog(
"*",
false,
false,
false);
1180 signal = doubleOutImage->GetPixel(index)*signalScale;
1182 if (m_Parameters.m_NoiseModel)
1183 m_Parameters.m_NoiseModel->AddNoise(signal);
1185 for (
unsigned int i=0; i<signal.Size(); i++)
1188 signal[i] = floor(signal[i]+0.5);
1190 signal[i] = ceil(signal[i]-0.5);
1192 if ( (!m_Parameters.m_SignalGen.IsBaselineIndex(i) || signal.Size()==1) && signal[i]>window)
1194 if ( (!m_Parameters.m_SignalGen.IsBaselineIndex(i) || signal.Size()==1) && signal[i]<min)
1201 unsigned int level = window/2 +
min;
1202 m_LevelWindow.SetLevelWindow(level, window);
1203 this->SetNthOutput(0, m_OutputImage);
1205 PrintToLog(
"\n",
false);
1206 PrintToLog(
"Finished simulation");
1209 if (m_Parameters.m_SignalGen.m_DoAddMotion)
1211 PrintToLog(
"\nHead motion log:",
false);
1212 PrintToLog(m_MotionLog,
false,
false);
1215 if (m_Parameters.m_SignalGen.m_Spikes>0)
1217 PrintToLog(
"\nSpike log:",
false);
1218 PrintToLog(m_SpikeLog,
false,
false);
1221 if (m_Logfile.is_open())
1226 template<
class PixelType >
1232 m_Logfile << this->GetTime() <<
" > ";
1233 m_StatusText += this->GetTime() +
" > ";
1235 std::cout << this->GetTime() <<
" > ";
1239 if (m_Logfile.is_open())
1248 if (m_Logfile.is_open())
1250 m_StatusText +=
"\n";
1256 template<
class PixelType >
1261 if ( m_Parameters.m_SignalGen.m_DoAddMotion
1262 && m_Parameters.m_SignalGen.m_MotionVolumes[g]
1263 && g<m_Parameters.m_SignalGen.GetNumVolumes() )
1265 if ( m_Parameters.m_SignalGen.m_DoRandomizeMotion )
1268 m_FiberBundleTransformed = m_FiberBundleWorkingCopy->GetDeepCopy();
1270 m_Rotation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[0]*2)
1271 -m_Parameters.m_SignalGen.m_Rotation[0];
1272 m_Rotation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[1]*2)
1273 -m_Parameters.m_SignalGen.m_Rotation[1];
1274 m_Rotation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[2]*2)
1275 -m_Parameters.m_SignalGen.m_Rotation[2];
1277 m_Translation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[0]*2)
1278 -m_Parameters.m_SignalGen.m_Translation[0];
1279 m_Translation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[1]*2)
1280 -m_Parameters.m_SignalGen.m_Translation[1];
1281 m_Translation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[2]*2)
1282 -m_Parameters.m_SignalGen.m_Translation[2];
1286 m_Rotation = m_Parameters.m_SignalGen.m_Rotation / m_NumMotionVolumes;
1287 m_Translation = m_Parameters.m_SignalGen.m_Translation / m_NumMotionVolumes;
1294 ImageRegionIterator<ItkUcharImgType> maskIt(m_UpsampledMaskImage, m_UpsampledMaskImage->GetLargestPossibleRegion());
1295 m_TransformedMaskImage->FillBuffer(0);
1297 while(!maskIt.IsAtEnd())
1299 if (maskIt.Get()<=0)
1305 DoubleDwiType::IndexType index = maskIt.GetIndex();
1306 itk::Point<double, 3> point;
1307 m_UpsampledMaskImage->TransformIndexToPhysicalPoint(index, point);
1308 if (m_Parameters.m_SignalGen.m_DoRandomizeMotion)
1310 point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(),
1311 m_Rotation[0],m_Rotation[1],m_Rotation[2],
1312 m_Translation[0],m_Translation[1],m_Translation[2]);
1316 point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(),
1317 m_Rotation[0]*m_MotionCounter,m_Rotation[1]*m_MotionCounter,m_Rotation[2]*m_MotionCounter,
1318 m_Translation[0]*m_MotionCounter,m_Translation[1]*m_MotionCounter,m_Translation[2]*m_MotionCounter);
1321 m_TransformedMaskImage->TransformPhysicalPointToIndex(point, index);
1323 if (m_TransformedMaskImage->GetLargestPossibleRegion().IsInside(index))
1324 { m_TransformedMaskImage->SetPixel(index,100); }
1329 if (m_Parameters.m_SignalGen.m_DoRandomizeMotion)
1331 m_Rotations.push_back(m_Rotation);
1332 m_Translations.push_back(m_Translation);
1334 m_MotionLog += boost::lexical_cast<std::string>(g) +
" rotation: " + boost::lexical_cast<std::string>(m_Rotation[0])
1335 +
"," + boost::lexical_cast<std::string>(m_Rotation[1])
1336 +
"," + boost::lexical_cast<std::string>(m_Rotation[2]) +
";";
1338 m_MotionLog +=
" translation: " + boost::lexical_cast<std::string>(m_Translation[0])
1339 +
"," + boost::lexical_cast<std::string>(m_Translation[1])
1340 +
"," + boost::lexical_cast<std::string>(m_Translation[2]) +
"\n";
1344 m_Rotations.push_back(m_Rotation*m_MotionCounter);
1345 m_Translations.push_back(m_Translation*m_MotionCounter);
1347 m_MotionLog += boost::lexical_cast<std::string>(g) +
" rotation: " + boost::lexical_cast<std::string>(m_Rotation[0]*m_MotionCounter)
1348 +
"," + boost::lexical_cast<std::string>(m_Rotation[1]*m_MotionCounter)
1349 +
"," + boost::lexical_cast<std::string>(m_Rotation[2]*m_MotionCounter) +
";";
1351 m_MotionLog +=
" translation: " + boost::lexical_cast<std::string>(m_Translation[0]*m_MotionCounter)
1352 +
"," + boost::lexical_cast<std::string>(m_Translation[1]*m_MotionCounter)
1353 +
"," + boost::lexical_cast<std::string>(m_Translation[2]*m_MotionCounter) +
"\n";
1356 m_FiberBundleTransformed->TransformFibers(m_Rotation[0],m_Rotation[1],m_Rotation[2],m_Translation[0],m_Translation[1],m_Translation[2]);
1360 m_Rotation.Fill(0.0);
1361 m_Translation.Fill(0.0);
1362 m_Rotations.push_back(m_Rotation);
1363 m_Translations.push_back(m_Translation);
1365 m_MotionLog += boost::lexical_cast<std::string>(g) +
" rotation: " + boost::lexical_cast<std::string>(m_Rotation[0])
1366 +
"," + boost::lexical_cast<std::string>(m_Rotation[1])
1367 +
"," + boost::lexical_cast<std::string>(m_Rotation[2]) +
";";
1369 m_MotionLog +=
" translation: " + boost::lexical_cast<std::string>(m_Translation[0])
1370 +
"," + boost::lexical_cast<std::string>(m_Translation[1])
1371 +
"," + boost::lexical_cast<std::string>(m_Translation[2]) +
"\n";
1375 template<
class PixelType >
1379 int numFiberCompartments = m_Parameters.m_FiberModelList.size();
1380 int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size();
1382 if (intraAxonalVolume>0.0001 && m_Parameters.m_SignalGen.m_DoDisablePartialVolume)
1386 pix[g] *= m_VoxelVolume/intraAxonalVolume;
1388 pix *= m_VoxelVolume/intraAxonalVolume;
1389 m_CompartmentImages.at(0)->SetPixel(index, pix);
1391 m_VolumeFractions.at(0)->SetPixel(index, 1);
1392 for (
int i=1; i<numFiberCompartments; i++)
1399 m_CompartmentImages.at(i)->SetPixel(index, pix);
1406 m_VolumeFractions.at(0)->SetPixel(index, intraAxonalVolume/m_VoxelVolume);
1411 itk::Point<double, 3> point;
1412 m_TransformedMaskImage->TransformIndexToPhysicalPoint(index, point);
1414 if ( m_Parameters.m_SignalGen.m_DoAddMotion && g>=0
1415 && m_Parameters.m_SignalGen.m_MotionVolumes[g] )
1417 if (m_Parameters.m_SignalGen.m_DoRandomizeMotion)
1419 point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(),
1420 -m_Rotation[0],-m_Rotation[1],-m_Rotation[2],
1421 -m_Translation[0],-m_Translation[1],-m_Translation[2]);
1425 point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(),
1426 -m_Rotation[0]*m_MotionCounter,-m_Rotation[1]*m_MotionCounter,-m_Rotation[2]*m_MotionCounter,
1427 -m_Translation[0]*m_MotionCounter,-m_Translation[1]*m_MotionCounter,-m_Translation[2]*m_MotionCounter);
1431 if (m_Parameters.m_SignalGen.m_DoDisablePartialVolume)
1433 int maxVolumeIndex = 0;
1434 double maxWeight = 0;
1435 for (
int i=0; i<numNonFiberCompartments; i++)
1438 if (numNonFiberCompartments>1)
1440 double val = InterpolateValue(point, m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage());
1447 if (weight>maxWeight)
1458 pix[g] += m_Parameters.m_NonFiberModelList[maxVolumeIndex]->SimulateMeasurement(g)*m_VoxelVolume;
1460 pix += m_Parameters.m_NonFiberModelList[maxVolumeIndex]->SimulateMeasurement()*m_VoxelVolume;
1461 doubleDwi->SetPixel(index, pix);
1463 m_VolumeFractions.at(maxVolumeIndex+numFiberCompartments)->SetPixel(index, 1);
1467 double extraAxonalVolume = m_VoxelVolume-intraAxonalVolume;
1468 if (extraAxonalVolume<0)
1470 MITK_ERROR <<
"Corrupted intra-axonal signal voxel detected. Fiber volume larger voxel volume!";
1471 extraAxonalVolume = 0;
1473 double interAxonalVolume = 0;
1474 if (numFiberCompartments>1)
1475 interAxonalVolume = extraAxonalVolume * intraAxonalVolume/m_VoxelVolume;
1476 double other = extraAxonalVolume - interAxonalVolume;
1479 MITK_ERROR <<
"Corrupted signal voxel detected. Fiber volume larger voxel volume!";
1484 for (
int i=1; i<numFiberCompartments; i++)
1486 double weight = interAxonalVolume;
1488 if (intraAxonalVolume>0)
1491 pix[g] /= intraAxonalVolume;
1493 pix /= intraAxonalVolume;
1496 if (m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage()!=
nullptr)
1498 double val = InterpolateValue(point, m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage());
1502 weight = val*m_VoxelVolume;
1509 m_CompartmentImages.at(i)->SetPixel(index, pix);
1511 m_VolumeFractions.at(i)->SetPixel(index, weight/m_VoxelVolume);
1514 for (
int i=0; i<numNonFiberCompartments; i++)
1516 double weight = other;
1518 if (m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()!=
nullptr)
1520 double val = InterpolateValue(point, m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage());
1524 weight = val*m_VoxelVolume;
1526 if (m_UseRelativeNonFiberVolumeFractions)
1527 weight *= other/m_VoxelVolume;
1531 pix[g] += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement(g)*weight;
1533 pix += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement()*weight;
1534 m_CompartmentImages.at(i+numFiberCompartments)->SetPixel(index, pix);
1536 m_VolumeFractions.at(i+numFiberCompartments)->SetPixel(index, weight/m_VoxelVolume);
1542 template<
class PixelType >
1547 itk::ContinuousIndex< double, 3> cIdx;
1548 img->TransformPhysicalPointToIndex(itkP, idx);
1549 img->TransformPhysicalPointToContinuousIndex(itkP, cIdx);
1552 if ( img->GetLargestPossibleRegion().IsInside(idx) )
1553 pix = img->GetPixel(idx);
1557 double frac_x = cIdx[0] - idx[0];
1558 double frac_y = cIdx[1] - idx[1];
1559 double frac_z = cIdx[2] - idx[2];
1580 if (idx[0] >= 0 && idx[0] < img->GetLargestPossibleRegion().GetSize(0)-1 &&
1581 idx[1] >= 0 && idx[1] < img->GetLargestPossibleRegion().GetSize(1)-1 &&
1582 idx[2] >= 0 && idx[2] < img->GetLargestPossibleRegion().GetSize(2)-1)
1584 vnl_vector_fixed<double, 8> interpWeights;
1585 interpWeights[0] = ( frac_x)*( frac_y)*( frac_z);
1586 interpWeights[1] = (1-frac_x)*( frac_y)*( frac_z);
1587 interpWeights[2] = ( frac_x)*(1-frac_y)*( frac_z);
1588 interpWeights[3] = ( frac_x)*( frac_y)*(1-frac_z);
1589 interpWeights[4] = (1-frac_x)*(1-frac_y)*( frac_z);
1590 interpWeights[5] = ( frac_x)*(1-frac_y)*(1-frac_z);
1591 interpWeights[6] = (1-frac_x)*( frac_y)*(1-frac_z);
1592 interpWeights[7] = (1-frac_x)*(1-frac_y)*(1-frac_z);
1594 pix = img->GetPixel(idx) * interpWeights[0];
1595 ItkDoubleImgType::IndexType tmpIdx = idx; tmpIdx[0]++;
1596 pix += img->GetPixel(tmpIdx) * interpWeights[1];
1597 tmpIdx = idx; tmpIdx[1]++;
1598 pix += img->GetPixel(tmpIdx) * interpWeights[2];
1599 tmpIdx = idx; tmpIdx[2]++;
1600 pix += img->GetPixel(tmpIdx) * interpWeights[3];
1601 tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++;
1602 pix += img->GetPixel(tmpIdx) * interpWeights[4];
1603 tmpIdx = idx; tmpIdx[1]++; tmpIdx[2]++;
1604 pix += img->GetPixel(tmpIdx) * interpWeights[5];
1605 tmpIdx = idx; tmpIdx[2]++; tmpIdx[0]++;
1606 pix += img->GetPixel(tmpIdx) * interpWeights[6];
1607 tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; tmpIdx[2]++;
1608 pix += img->GetPixel(tmpIdx) * interpWeights[7];
1614 template<
class PixelType >
1617 itk::Point<float, 3> itkPoint;
1618 itkPoint[0] = point[0];
1619 itkPoint[1] = point[1];
1620 itkPoint[2] = point[2];
1624 template<
class PixelType >
1627 itk::Vector<double, 3> itkVector;
1628 itkVector[0] = point[0];
1629 itkVector[1] = point[1];
1630 itkVector[2] = point[2];
1634 template<
class PixelType >
1637 vnl_vector_fixed<double, 3> vnlVector;
1638 vnlVector[0] = point[0];
1639 vnlVector[1] = point[1];
1640 vnlVector[2] = point[2];
1644 template<
class PixelType >
1647 vnl_vector_fixed<double, 3> vnlVector;
1648 vnlVector[0] = vector[0];
1649 vnlVector[1] = vector[1];
1650 vnlVector[2] = vector[2];
1654 template<
class PixelType >
1656 return (num > 0.0) ? floor(num + 0.5) : ceil(num - 0.5);
1659 template<
class PixelType >
1663 unsigned long total = RoundToNearest(m_TimeProbe.GetTotal());
1664 unsigned long hours = total/3600;
1665 unsigned long minutes = (total%3600)/60;
1666 unsigned long seconds = total%60;
1667 std::string out =
"";
1668 out.append(boost::lexical_cast<std::string>(hours));
1670 out.append(boost::lexical_cast<std::string>(minutes));
1672 out.append(boost::lexical_cast<std::string>(seconds));
1673 m_TimeProbe.Start();
void PrintToLog(string m, bool addTime=true, bool linebreak=true, bool stdOut=true)
virtual ~TractsToDWIImageFilter()
itk::SmartPointer< Self > Pointer
void SimulateExtraAxonalSignal(ItkUcharImgType::IndexType index, double intraAxonalVolume, int g=-1)
Generates artificial diffusion weighted image volume from the input fiberbundle using a generic multi...
static std::string GetTempPath()
ItkDoubleImgType::Pointer NormalizeInsideMask(ItkDoubleImgType::Pointer image)
DoubleDwiType::Pointer SimulateKspaceAcquisition(std::vector< DoubleDwiType::Pointer > &images)
itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen
Abstract class for diffusion signal models.
void SimulateMotion(int g=-1)
itk::Vector< double, 3 > DoubleVectorType
itk::Point< float, 3 > GetItkPoint(double point[3])
double InterpolateValue(itk::Point< float, 3 > itkP, ItkDoubleImgType::Pointer img)
double RoundToNearest(double num)
Resample DWI channel by channel.
void CheckVolumeFractionImages()
vnl_vector_fixed< double, 3 > GetVnlVector(double point[3])
itk::Vector< double, 3 > GetItkVector(double point[3])
void InitializeFiberData()
section MAP_FRAME_Mapper_Settings Mapper settings For the mapping of corrected images
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.