16 #ifndef __itkDwiPhantomGenerationFilter_cpp
17 #define __itkDwiPhantomGenerationFilter_cpp
24 #include <itkImageRegionConstIterator.h>
25 #include <itkImageRegionConstIteratorWithIndex.h>
26 #include <itkImageRegionIterator.h>
29 #include <vtkSmartPointer.h>
30 #include <vtkPolyData.h>
31 #include <vtkCellArray.h>
32 #include <vtkPoints.h>
33 #include <vtkPolyLine.h>
35 #include <boost/progress.hpp>
40 template<
class TOutputScalarType >
48 , m_NoiseVariance(0.004)
49 , m_AddNoiseFlag(true)
50 , m_GreyMatterAdc(0.01)
51 , m_SimulateBaseline(true)
52 , m_DefaultBaseline(1000)
54 this->SetNumberOfRequiredOutputs (1);
55 m_Spacing.Fill(2.5); m_Origin.Fill(0.0);
56 m_DirectionMatrix.SetIdentity();
57 m_ImageRegion.SetSize(0, 10);
58 m_ImageRegion.SetSize(1, 10);
59 m_ImageRegion.SetSize(2, 10);
63 outImage->SetSpacing( m_Spacing );
64 outImage->SetOrigin( m_Origin );
65 outImage->SetDirection( m_DirectionMatrix );
66 outImage->SetLargestPossibleRegion( m_ImageRegion );
67 outImage->SetBufferedRegion( m_ImageRegion );
68 outImage->SetRequestedRegion( m_ImageRegion );
74 outImage->FillBuffer( fillValue );
76 this->SetNthOutput (0, outImage);
81 template<
class TOutputScalarType >
87 for (
int i=0; i<m_SignalRegions.size(); i++)
89 float ADC = m_TensorADC.at(i);
90 float FA = m_TensorFA.at(i);
91 itk::DiffusionTensor3D<float> kernel;
93 float e1=ADC*(1+2*FA/sqrt(3-2*FA*FA));
94 float e2=ADC*(1-FA/sqrt(3-2*FA*FA));
96 kernel.SetElement(0,e1);
97 kernel.SetElement(3,e2);
98 kernel.SetElement(5,e3);
100 if (m_SimulateBaseline)
102 double l2 = GetTensorL2Norm(kernel);
103 if (l2>m_MaxBaseline)
107 MITK_INFO <<
"Kernel FA: " << kernel.GetFractionalAnisotropy();
108 vnl_vector_fixed<double, 3> kernelDir; kernelDir[0]=1; kernelDir[1]=0; kernelDir[2]=0;
110 itk::DiffusionTensor3D<float> tensor;
111 vnl_vector_fixed<double, 3> dir = m_TensorDirection.at(i);
112 MITK_INFO <<
"Tensor direction: " << dir;
116 vnl_vector_fixed<double, 3> axis = vnl_cross_3d(kernelDir, dir); axis.normalize();
117 vnl_quaternion<double>
rotation(axis, acos(dot_product(kernelDir, dir)));
119 vnl_matrix_fixed<double, 3, 3> matrix =
rotation.rotation_matrix_transpose();
121 vnl_matrix_fixed<double, 3, 3> tensorMatrix;
122 tensorMatrix[0][0] = kernel[0]; tensorMatrix[0][1] = kernel[1]; tensorMatrix[0][2] = kernel[2];
123 tensorMatrix[1][0] = kernel[1]; tensorMatrix[1][1] = kernel[3]; tensorMatrix[1][2] = kernel[4];
124 tensorMatrix[2][0] = kernel[2]; tensorMatrix[2][1] = kernel[4]; tensorMatrix[2][2] = kernel[5];
126 tensorMatrix = matrix.transpose()*tensorMatrix*matrix;
127 tensor[0] = tensorMatrix[0][0]; tensor[1] = tensorMatrix[0][1]; tensor[2] = tensorMatrix[0][2];
128 tensor[3] = tensorMatrix[1][1]; tensor[4] = tensorMatrix[1][2]; tensor[5] = tensorMatrix[2][2];
130 m_TensorList.push_back(tensor);
134 template<
class TOutputScalarType >
137 for(
unsigned int i=0; i<m_GradientList.size(); i++)
139 float signal = pix[i];
140 float val = sqrt(pow(signal + m_SignalScale*m_RandGen->GetNormalVariate(0.0, m_NoiseVariance), 2) + pow(m_SignalScale*m_RandGen->GetNormalVariate(0.0, m_NoiseVariance),2));
145 template<
class TOutputScalarType >
147 DwiPhantomGenerationFilter< TOutputScalarType >::SimulateMeasurement(itk::DiffusionTensor3D<float>& T,
float weight)
150 out.SetSize(m_GradientList.size());
153 TOutputScalarType s0 = m_DefaultBaseline;
154 if (m_SimulateBaseline)
155 s0 = (GetTensorL2Norm(T)/m_MaxBaseline)*m_SignalScale;
157 for(
unsigned int i=0; i<m_GradientList.size(); i++)
159 GradientType g = m_GradientList[i];
161 if (g.GetNorm()>0.0001)
163 itk::DiffusionTensor3D<float> S;
171 double D = T[0]*S[0] + T[1]*S[1] + T[2]*S[2] +
172 T[1]*S[1] + T[3]*S[3] + T[4]*S[4] +
173 T[2]*S[2] + T[4]*S[4] + T[5]*S[5];
178 D = weight*s0*exp ( -m_BValue * D );
179 out[i] =
static_cast<TOutputScalarType
>( D );
189 template<
class TOutputScalarType >
193 if (m_NoiseVariance < 0 && m_AddNoiseFlag)
195 m_NoiseVariance = 0.001;
198 if (!m_SimulateBaseline)
200 MITK_INFO <<
"Baseline image values are set to default. Noise variance value is treated as SNR!";
201 if (m_NoiseVariance <= 0 && m_AddNoiseFlag)
203 m_NoiseVariance = 0.0001;
205 else if (m_NoiseVariance>99 && m_AddNoiseFlag)
211 m_NoiseVariance = m_DefaultBaseline/(m_NoiseVariance*m_SignalScale);
212 m_NoiseVariance *= m_NoiseVariance;
217 m_RandGen->SetSeed();
220 outImage->SetSpacing( m_Spacing );
221 outImage->SetOrigin( m_Origin );
222 outImage->SetDirection( m_DirectionMatrix );
223 outImage->SetLargestPossibleRegion( m_ImageRegion );
224 outImage->SetBufferedRegion( m_ImageRegion );
225 outImage->SetRequestedRegion( m_ImageRegion );
226 outImage->SetVectorLength(m_GradientList.size());
227 outImage->Allocate();
229 pix.SetSize(m_GradientList.size());
231 outImage->FillBuffer(pix);
232 this->SetNthOutput (0, outImage);
234 double minSpacing = m_Spacing[0];
235 if (m_Spacing[1]<minSpacing)
236 minSpacing = m_Spacing[1];
237 if (m_Spacing[2]<minSpacing)
238 minSpacing = m_Spacing[2];
241 for (
int i=0; i<m_SignalRegions.size(); i++)
243 itk::Vector< float, 3 > nullVec; nullVec.Fill(0.0);
245 img->SetSpacing( m_Spacing );
246 img->SetOrigin( m_Origin );
247 img->SetDirection( m_DirectionMatrix );
248 img->SetRegions( m_ImageRegion );
250 img->FillBuffer(nullVec);
251 m_DirectionImageContainer->InsertElement(m_DirectionImageContainer->Size(), img);
254 m_NumDirectionsImage->SetSpacing( m_Spacing );
255 m_NumDirectionsImage->SetOrigin( m_Origin );
256 m_NumDirectionsImage->SetDirection( m_DirectionMatrix );
257 m_NumDirectionsImage->SetRegions( m_ImageRegion );
258 m_NumDirectionsImage->Allocate();
259 m_NumDirectionsImage->FillBuffer(0);
262 m_SNRImage->SetSpacing( m_Spacing );
263 m_SNRImage->SetOrigin( m_Origin );
264 m_SNRImage->SetDirection( m_DirectionMatrix );
265 m_SNRImage->SetRegions( m_ImageRegion );
266 m_SNRImage->Allocate();
267 m_SNRImage->FillBuffer(0);
272 m_BaselineImages = 0;
273 for(
unsigned int i=0; i<m_GradientList.size(); i++)
274 if (m_GradientList[i].GetNorm()<=0.0001)
277 typedef ImageRegionIterator<OutputImageType> IteratorOutputType;
278 IteratorOutputType it (outImage, m_ImageRegion);
281 itk::DiffusionTensor3D<float> isoTensor;
283 float e1 = m_GreyMatterAdc;
284 float e2 = m_GreyMatterAdc;
285 float e3 = m_GreyMatterAdc;
286 isoTensor.SetElement(0,e1);
287 isoTensor.SetElement(3,e2);
288 isoTensor.SetElement(5,e3);
289 m_MaxBaseline = GetTensorL2Norm(isoTensor);
295 double noiseStdev = sqrt(m_NoiseVariance);
299 typename OutputImageType::IndexType index = it.GetIndex();
302 for (
int i=0; i<m_SignalRegions.size(); i++)
306 if (region->GetPixel(index)!=0)
309 pix += SimulateMeasurement(m_TensorList[i], m_TensorWeight[i]);
313 itk::Vector< float, 3 > pixel = img->GetPixel(index);
314 vnl_vector_fixed<double, 3> dir = m_TensorDirection.at(i);
316 dir *= m_TensorWeight.at(i);
317 pixel.SetElement(0, dir[0]);
318 pixel.SetElement(1, dir[1]);
319 pixel.SetElement(2, dir[2]);
320 img->SetPixel(index, pixel);
323 itk::ContinuousIndex<double, 3> center;
324 center[0] = index[0];
325 center[1] = index[1];
326 center[2] = index[2];
327 itk::Point<double> worldCenter;
328 outImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter );
329 itk::Point<double> worldStart;
330 worldStart[0] = worldCenter[0]-dir[0]/2 * minSpacing;
331 worldStart[1] = worldCenter[1]-dir[1]/2 * minSpacing;
332 worldStart[2] = worldCenter[2]-dir[2]/2 * minSpacing;
333 vtkIdType
id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer());
334 container->GetPointIds()->InsertNextId(
id);
335 itk::Point<double> worldEnd;
336 worldEnd[0] = worldCenter[0]+dir[0]/2 * minSpacing;
337 worldEnd[1] = worldCenter[1]+dir[1]/2 * minSpacing;
338 worldEnd[2] = worldCenter[2]+dir[2]/2 * minSpacing;
339 id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer());
340 container->GetPointIds()->InsertNextId(
id);
341 m_VtkCellArray->InsertNextCell(container);
347 for (
int i=0; i<m_GradientList.size(); i++) { pix[i] /= numDirs; }
352 if (m_SimulateBaseline) { pix = SimulateMeasurement(isoTensor, 1.0); }
354 else { pix.Fill(0.0); }
358 m_MeanBaseline += pix[0];
360 m_NumDirectionsImage->SetPixel(index, numDirs);
361 if (m_NoiseVariance>0 && m_AddNoiseFlag)
363 m_SNRImage->SetPixel(index, pix[0]/(noiseStdev*m_SignalScale));
367 m_MeanBaseline /= m_ImageRegion.GetNumberOfPixels();
368 if (m_NoiseVariance>0 && m_AddNoiseFlag)
370 MITK_INFO <<
"Mean SNR: " << m_MeanBaseline/(noiseStdev*m_SignalScale);
389 directionsPolyData->SetPoints(m_VtkPoints);
390 directionsPolyData->SetLines(m_VtkCellArray);
393 template<
class TOutputScalarType >
396 return sqrt(T[0]*T[0] + T[3]*T[3] + T[5]*T[5] + T[1]*T[2]*2.0 + T[2]*T[4]*2.0 + T[1]*T[4]*2.0);
401 #endif // __itkDwiPhantomGenerationFilter_cpp
itk::SmartPointer< Self > Pointer
Generation of synthetic diffusion weighted images using a second rank tensor model.
DwiPhantomGenerationFilter()
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.