17 #ifndef __itkKspaceImageFilter_txx
18 #define __itkKspaceImageFilter_txx
25 #include <itkImageRegionConstIterator.h>
26 #include <itkImageRegionConstIteratorWithIndex.h>
27 #include <itkImageRegionIterator.h>
28 #include <itkImageFileWriter.h>
32 #define _USE_MATH_DEFINES
37 template<
class TPixelType >
41 , m_UseConstantRandSeed(false)
45 m_DiffusionGradientDirection.Fill(0.0);
47 m_CoilPosition.Fill(0.0);
50 template<
class TPixelType >
54 m_Spike = vcl_complex<double>(0,0);
58 itk::ImageRegion<2> region;
59 region.SetSize(0, m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(0));
60 region.SetSize(1, m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(1));
61 outputImage->SetLargestPossibleRegion( region );
62 outputImage->SetBufferedRegion( region );
63 outputImage->SetRequestedRegion( region );
64 outputImage->Allocate();
65 outputImage->FillBuffer(m_Spike);
68 m_KSpaceImage->SetLargestPossibleRegion( region );
69 m_KSpaceImage->SetBufferedRegion( region );
70 m_KSpaceImage->SetRequestedRegion( region );
71 m_KSpaceImage->Allocate();
72 m_KSpaceImage->FillBuffer(0.0);
75 if ( m_Parameters->m_SignalGen.m_EddyStrength>0 && m_DiffusionGradientDirection.GetNorm()>0.001)
77 m_DiffusionGradientDirection.Normalize();
78 m_DiffusionGradientDirection = m_DiffusionGradientDirection * m_Parameters->m_SignalGen.m_EddyStrength/1000 * m_Gamma;
82 this->SetNthOutput(0, outputImage);
84 m_Transform = m_Parameters->m_SignalGen.m_ImageDirection;
85 for (
int i=0; i<3; i++)
87 for (
int j=0; j<3; j++)
89 m_Transform[i][j] *= m_Parameters->m_SignalGen.m_ImageSpacing[j];
92 double a = m_Parameters->m_SignalGen.m_ImageRegion.GetSize(0)*m_Parameters->m_SignalGen.m_ImageSpacing[0];
93 double b = m_Parameters->m_SignalGen.m_ImageRegion.GetSize(1)*m_Parameters->m_SignalGen.m_ImageSpacing[1];
94 double diagonal = sqrt(a*a+b*b)/1000;
96 switch (m_Parameters->m_SignalGen.m_CoilSensitivityProfile)
98 case SignalGenerationParameters::COIL_CONSTANT:
100 m_CoilSensitivityFactor = 1;
103 case SignalGenerationParameters::COIL_LINEAR:
105 m_CoilSensitivityFactor = -1/diagonal;
108 case SignalGenerationParameters::COIL_EXPONENTIAL:
110 m_CoilSensitivityFactor = -log(0.1)/diagonal;
115 switch (m_Parameters->m_SignalGen.m_AcquisitionType)
117 case SignalGenerationParameters::SingleShotEpi:
120 case SignalGenerationParameters::SpinEcho:
127 m_ReadoutScheme->AdjustEchoTime();
130 template<
class TPixelType >
135 m_CoilPosition[2] = pos[2];
138 switch (m_Parameters->m_SignalGen.m_CoilSensitivityProfile)
140 case SignalGenerationParameters::COIL_CONSTANT:
142 case SignalGenerationParameters::COIL_LINEAR:
145 double sens = diff.GetNorm()*m_CoilSensitivityFactor + 1;
150 case SignalGenerationParameters::COIL_EXPONENTIAL:
153 double dist = diff.GetNorm();
154 return exp(-dist*m_CoilSensitivityFactor);
161 template<
class TPixelType >
167 if (m_UseConstantRandSeed)
178 ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
180 typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
182 double kxMax = m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(0);
183 double kyMax = m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(1);
184 double xMax = m_CompartmentImages.at(0)->GetLargestPossibleRegion().GetSize(0);
185 double yMax = m_CompartmentImages.at(0)->GetLargestPossibleRegion().GetSize(1);
186 double yMaxFov = yMax*m_Parameters->m_SignalGen.m_CroppingFactor;
188 double numPix = kxMax*kyMax;
190 double noiseVar = m_Parameters->m_SignalGen.m_PartialFourier*m_Parameters->m_SignalGen.m_NoiseVariance/(kyMax*kxMax);
192 while( !oit.IsAtEnd() )
195 double t= m_ReadoutScheme->GetTimeFromMaxEcho(oit.GetIndex());
198 double tRead = m_ReadoutScheme->GetRedoutTime(oit.GetIndex());
201 double tRf = m_Parameters->m_SignalGen.m_tEcho+t;
205 double eddyDecay = 0;
206 if ( m_Parameters->m_Misc.m_CheckAddEddyCurrentsBox && m_Parameters->m_SignalGen.m_EddyStrength>0)
208 eddyDecay = exp(-tRead/m_Parameters->m_SignalGen.m_Tau );
212 std::vector< double > relaxFactor;
213 if ( m_Parameters->m_SignalGen.m_DoSimulateRelaxation)
215 for (
unsigned int i=0; i<m_CompartmentImages.size(); i++)
217 relaxFactor.push_back( exp(-tRf/m_T2.at(i) -fabs(t)/ m_Parameters->m_SignalGen.m_tInhom)
218 * (1.0-exp(-(m_Parameters->m_SignalGen.m_tRep + tRf)/m_T1.at(i))) );
222 itk::Index< 2 > kIdx = m_ReadoutScheme->GetActualKspaceIndex(oit.GetIndex());
226 if (kIdx[1]>kyMax*m_Parameters->m_SignalGen.m_PartialFourier)
236 if ((
int)kxMax%2==1){ kx -= (kxMax-1)/2; }
237 else{ kx -= kxMax/2; }
239 if ((
int)kyMax%2==1){ ky -= (kyMax-1)/2; }
240 else{ ky -= kyMax/2; }
243 if (oit.GetIndex()[1]%2 == 1)
245 kx -= m_Parameters->m_SignalGen.m_KspaceLineOffset;
249 kx += m_Parameters->m_SignalGen.m_KspaceLineOffset;
252 vcl_complex<double> s(0,0);
253 InputIteratorType it(m_CompartmentImages.at(0), m_CompartmentImages.at(0)->GetLargestPossibleRegion() );
254 while( !it.IsAtEnd() )
256 double x = it.GetIndex()[0];
257 double y = it.GetIndex()[1];
258 if ((
int)xMax%2==1){ x -= (xMax-1)/2; }
260 if ((
int)yMax%2==1){ y -= (yMax-1)/2; }
264 pos = m_Transform*pos/1000;
266 vcl_complex<double> f(0, 0);
269 for (
unsigned int i=0; i<m_CompartmentImages.size(); i++)
270 if ( m_Parameters->m_SignalGen.m_DoSimulateRelaxation)
271 f += std::complex<double>( m_CompartmentImages.at(i)->GetPixel(it.GetIndex()) * relaxFactor.at(i) * m_Parameters->m_SignalGen.m_SignalScale, 0);
273 f += std::complex<double>( m_CompartmentImages.at(i)->GetPixel(it.GetIndex()) * m_Parameters->m_SignalGen.m_SignalScale );
275 if (m_Parameters->m_SignalGen.m_CoilSensitivityProfile!=SignalGenerationParameters::COIL_CONSTANT)
276 f *= CoilSensitivity(pos);
280 if ( m_Parameters->m_SignalGen.m_EddyStrength>0 && m_Parameters->m_Misc.m_CheckAddEddyCurrentsBox && !m_IsBaseline)
282 omega += (m_DiffusionGradientDirection[0]*pos[0]+m_DiffusionGradientDirection[1]*pos[1]+m_DiffusionGradientDirection[2]*pos[2]) * eddyDecay;
285 if (m_Parameters->m_SignalGen.m_FrequencyMap.IsNotNull())
287 itk::Point<double, 3> point3D;
288 ItkDoubleImgType::IndexType index; index[0] = it.GetIndex()[0]; index[1] = it.GetIndex()[1]; index[2] = m_Zidx;
289 if (m_Parameters->m_SignalGen.m_DoAddMotion)
291 m_Parameters->m_SignalGen.m_FrequencyMap->TransformIndexToPhysicalPoint(index, point3D);
292 point3D = m_FiberBundle->TransformPoint( point3D.GetVnlVector(),
293 -m_Rotation[0], -m_Rotation[1], -m_Rotation[2],
294 -m_Translation[0], -m_Translation[1], -m_Translation[2] );
295 omega += InterpolateFmapValue(point3D);
299 omega += m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(index);
305 if (y<-yMaxFov/2){ y += yMaxFov; }
306 else if (y>=yMaxFov/2) { y -= yMaxFov; }
309 s += f * exp( std::complex<double>(0, 2 *
M_PI * (kx*x/xMax + ky*y/yMaxFov + omega*t/1000 )) );
315 if (m_SpikesPerSlice>0 && sqrt(s.imag()*s.imag()+s.real()*s.real()) > sqrt(m_Spike.imag()*m_Spike.imag()+m_Spike.real()*m_Spike.real()) )
321 if (m_Parameters->m_SignalGen.m_NoiseVariance>0 && m_Parameters->m_Misc.m_CheckAddNoiseBox)
323 s = vcl_complex<double>(s.real()+randGen->GetNormalVariate(0,noiseVar), s.imag()+randGen->GetNormalVariate(0,noiseVar));
326 outputImage->SetPixel(kIdx, s);
327 m_KSpaceImage->SetPixel(kIdx, sqrt(s.imag()*s.imag()+s.real()*s.real()) );
334 template<
class TPixelType >
338 delete m_ReadoutScheme;
341 double kxMax = outputImage->GetLargestPossibleRegion().GetSize(0);
342 double kyMax = outputImage->GetLargestPossibleRegion().GetSize(1);
344 ImageRegionIterator< OutputImageType > oit(outputImage, outputImage->GetLargestPossibleRegion());
345 while( !oit.IsAtEnd() )
348 kIdx[0] = oit.GetIndex()[0];
349 kIdx[1] = oit.GetIndex()[1];
352 if (!m_Parameters->m_SignalGen.m_ReversePhase)
353 kIdx[1] = kyMax-1-kIdx[1];
355 if (kIdx[1]>kyMax*m_Parameters->m_SignalGen.m_PartialFourier)
358 if (oit.GetIndex()[1]%2 == 1)
359 kIdx[0] = kxMax-kIdx[0]-1;
363 kIdx2[0] = (int)(kxMax-kIdx[0]-(
int)kxMax%2)%(
int)kxMax;
364 kIdx2[1] = (int)(kyMax-kIdx[1]-(
int)kyMax%2)%(
int)kyMax;
367 vcl_complex<double> s = outputImage->GetPixel(kIdx2);
368 s = vcl_complex<double>(s.real(), -s.imag());
369 outputImage->SetPixel(kIdx, s);
371 m_KSpaceImage->SetPixel(kIdx, sqrt(s.imag()*s.imag()+s.real()*s.real()) );
378 if (m_UseConstantRandSeed)
383 m_Spike *= m_Parameters->m_SignalGen.m_SpikeAmplitude;
385 for (
unsigned int i=0; i<m_SpikesPerSlice; i++)
387 spikeIdx[0] = randGen->GetIntegerVariate()%(int)kxMax;
388 spikeIdx[1] = randGen->GetIntegerVariate()%(int)kyMax;
389 outputImage->SetPixel(spikeIdx, m_Spike);
390 m_SpikeLog +=
"[" + boost::lexical_cast<std::string>(spikeIdx[0]) +
"," + boost::lexical_cast<std::string>(spikeIdx[1]) +
"," + boost::lexical_cast<std::string>(m_Zidx) +
"] Magnitude: " + boost::lexical_cast<std::string>(m_Spike.real()) +
"+" + boost::lexical_cast<std::string>(m_Spike.imag()) +
"i\n";
396 template<
class TPixelType >
400 itk::ContinuousIndex< double, 3> cIdx;
401 m_Parameters->m_SignalGen.m_FrequencyMap->TransformPhysicalPointToIndex(itkP, idx);
402 m_Parameters->m_SignalGen.m_FrequencyMap->TransformPhysicalPointToContinuousIndex(itkP, cIdx);
405 if ( m_Parameters->m_SignalGen.m_FrequencyMap->GetLargestPossibleRegion().IsInside(idx) )
406 pix = m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(idx);
410 double frac_x = cIdx[0] - idx[0];
411 double frac_y = cIdx[1] - idx[1];
412 double frac_z = cIdx[2] - idx[2];
433 if (idx[0] >= 0 && idx[0] < m_Parameters->m_SignalGen.m_FrequencyMap->GetLargestPossibleRegion().GetSize(0)-1 &&
434 idx[1] >= 0 && idx[1] < m_Parameters->m_SignalGen.m_FrequencyMap->GetLargestPossibleRegion().GetSize(1)-1 &&
435 idx[2] >= 0 && idx[2] < m_Parameters->m_SignalGen.m_FrequencyMap->GetLargestPossibleRegion().GetSize(2)-1)
437 vnl_vector_fixed<double, 8> interpWeights;
438 interpWeights[0] = ( frac_x)*( frac_y)*( frac_z);
439 interpWeights[1] = (1-frac_x)*( frac_y)*( frac_z);
440 interpWeights[2] = ( frac_x)*(1-frac_y)*( frac_z);
441 interpWeights[3] = ( frac_x)*( frac_y)*(1-frac_z);
442 interpWeights[4] = (1-frac_x)*(1-frac_y)*( frac_z);
443 interpWeights[5] = ( frac_x)*(1-frac_y)*(1-frac_z);
444 interpWeights[6] = (1-frac_x)*( frac_y)*(1-frac_z);
445 interpWeights[7] = (1-frac_x)*(1-frac_y)*(1-frac_z);
447 pix = m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(idx) * interpWeights[0];
448 ItkDoubleImgType::IndexType tmpIdx = idx; tmpIdx[0]++;
449 pix += m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(tmpIdx) * interpWeights[1];
450 tmpIdx = idx; tmpIdx[1]++;
451 pix += m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(tmpIdx) * interpWeights[2];
452 tmpIdx = idx; tmpIdx[2]++;
453 pix += m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(tmpIdx) * interpWeights[3];
454 tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++;
455 pix += m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(tmpIdx) * interpWeights[4];
456 tmpIdx = idx; tmpIdx[1]++; tmpIdx[2]++;
457 pix += m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(tmpIdx) * interpWeights[5];
458 tmpIdx = idx; tmpIdx[2]++; tmpIdx[0]++;
459 pix += m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(tmpIdx) * interpWeights[6];
460 tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; tmpIdx[2]++;
461 pix += m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(tmpIdx) * interpWeights[7];
double CoilSensitivity(DoubleVectorType &pos)
itk::SmartPointer< Self > Pointer
double InterpolateFmapValue(itk::Point< float, 3 > itkP)
void BeforeThreadedGenerateData()
If an imaging filter needs to perform processing after the buffer has been allocated but before threa...
Superclass::OutputImageRegionType OutputImageRegionType
Realizes EPI readout: one echo, maximum intensity in the k-space center, zig-zag trajectory.
Image class for storing images.
itk::Vector< double, 3 > DoubleVectorType
Realizes EPI readout: one echo, maximum intensity in the k-space center, zig-zag trajectory.
void AfterThreadedGenerateData()
If an imaging filter needs to perform processing after all processing threads have completed...
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadID)
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.