4 #include <itkMultiThreaderBase.h> 11 template<
class TInputImage,
class TCoordRep>
13 MCMLinearInterpolateImageFunction< TInputImage, TCoordRep >
14 ::m_Neighbors = 1 << TInputImage::ImageDimension;
20 template<
class TInputImage,
class TCoordRep>
26 template<
class TInputImage,
class TCoordRep>
31 this->Superclass::SetInputImage(ptr);
36 if (m_MCMAveragers.size() != 0)
38 if (m_MCMAveragers[0].IsNotNull())
39 this->TestModelsAdequation(model,m_MCMAveragers[0]->GetUntouchedOutputModel());
42 unsigned int numThreads = itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads();
43 m_ReferenceInputModels.resize(numThreads);
44 m_ReferenceInputWeights.resize(numThreads);
45 for (
unsigned int i = 0;i < numThreads;++i)
47 m_ReferenceInputModels[i].resize(m_Neighbors);
48 m_ReferenceInputWeights[i].resize(m_Neighbors);
49 std::fill(m_ReferenceInputWeights[i].begin(),m_ReferenceInputWeights[i].end(),0.0);
50 for (
unsigned int j = 0;j < m_Neighbors;++j)
51 m_ReferenceInputModels[i][j] = model->Clone();
55 template<
class TInputImage,
class TCoordRep>
60 if (this->GetInputImage() != 0)
61 this->TestModelsAdequation(m_ReferenceInputModels[0][0],model);
63 this->ResetAveragePointers(model);
66 template<
class TInputImage,
class TCoordRep>
71 unsigned int numThreads = itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads();
72 m_MCMAveragers.resize(numThreads);
74 for (
unsigned int i = 0;i < numThreads;++i)
76 m_MCMAveragers[i] = AveragerType::New();
77 m_MCMAveragers[i]->SetOutputModel(model);
81 template<
class TInputImage,
class TCoordRep>
86 unsigned int numIsoCompartments = model->GetNumberOfIsotropicCompartments();
87 if (!model->GetCompartment(numIsoCompartments)->GetTensorCompatible())
93 template<
class TInputImage,
class TCoordRep>
98 unsigned int numIsoCompartmentsInput = inputModel->GetNumberOfIsotropicCompartments();
99 unsigned int numIsoCompartmentsOutput = outputModel->GetNumberOfIsotropicCompartments();
101 if (numIsoCompartmentsInput != numIsoCompartmentsOutput)
102 itkExceptionMacro(
"Cannot handle interpolation to model with different number of isotropic compartments.");
104 for (
unsigned int i = 0;i < numIsoCompartmentsInput;++i)
106 if (outputModel->GetCompartment(i)->GetCompartmentType() != inputModel->GetCompartment(i)->GetCompartmentType())
107 itkExceptionMacro(
"Interpolation only of models with the same isotropic compartment types.");
110 if (outputModel->GetNumberOfCompartments() - numIsoCompartmentsOutput > 0)
112 if (outputModel->GetCompartment(numIsoCompartmentsOutput)->GetCompartmentType()
113 != inputModel->GetCompartment(numIsoCompartmentsOutput)->GetCompartmentType())
114 itkExceptionMacro(
"Interpolation of non tensor compatible models only to the same compartment type.");
116 if (!this->CheckModelCompatibility(outputModel))
117 itkExceptionMacro(
"Model not yet supported by MCM linear interpolation");
122 template<
class TInputImage,
class TCoordRep>
127 m_LockUsedModels.lock();
129 unsigned int workIndex = 0;
130 bool workIndexOk =
false;
132 while ((!workIndexOk)&&(workIndex < m_ReferenceInputModels.size()))
135 for (
unsigned int i = 0;i < m_UsedModels.size();++i)
137 if (m_UsedModels[i] == workIndex)
148 m_UsedModels.push_back(workIndex);
149 m_LockUsedModels.unlock();
154 template<
class TInputImage,
class TCoordRep>
159 m_LockUsedModels.lock();
161 for (
unsigned int i = 0;i < m_UsedModels.size();++i)
163 if (m_UsedModels[i] == index)
165 m_UsedModels.erase(m_UsedModels.begin() + i);
170 m_LockUsedModels.unlock();
176 template<
class TInputImage,
class TCoordRep>
183 double distance[ImageDimension], oppDistance[ImageDimension];
185 for (
unsigned int dim = 0; dim < ImageDimension; ++dim)
187 baseIndex[dim] = itk::Math::Floor< IndexValueType >( index[dim] );
188 distance[dim] = index[dim] -
static_cast< double >( baseIndex[dim] );
189 oppDistance[dim] = 1.0 - distance[dim];
192 unsigned int threadIndex = this->GetFreeWorkIndex();
194 OutputType voxelOutputValue(m_MCMAveragers[threadIndex]->GetOutputModelSize());
195 voxelOutputValue.Fill(0);
196 std::fill(m_ReferenceInputWeights[threadIndex].begin(),m_ReferenceInputWeights[threadIndex].end(),0.0);
198 this->SetSpecificAveragerParameters(threadIndex);
199 m_MCMAveragers[threadIndex]->ResetNumberOfOutputDirectionalCompartments();
201 double totalOverlap = 0;
203 unsigned int posMCM = 0;
204 unsigned int maxNumCompartments = 0;
206 unsigned int numIsoCompartments = m_ReferenceInputModels[threadIndex][0]->GetNumberOfIsotropicCompartments();
207 unsigned int numberOfTotalInputCompartments = m_ReferenceInputModels[threadIndex][0]->GetNumberOfCompartments();
209 for (
unsigned int counterInput = 0;counterInput < m_Neighbors;++counterInput)
211 double overlap = 1.0;
212 unsigned int upper = counterInput;
217 for (
unsigned int dim = 0; dim < ImageDimension; ++dim)
221 neighIndex[dim] = baseIndex[dim] + 1;
223 if (neighIndex[dim] > this->m_EndIndex[dim])
229 overlap *= distance[dim];
233 neighIndex[dim] = baseIndex[dim];
235 if (neighIndex[dim] < this->m_StartIndex[dim])
241 overlap *= oppDistance[dim];
248 if ((overlap > 0) && okValue)
250 const PixelType input = this->GetInputImage()->GetPixel( neighIndex );
254 m_ReferenceInputModels[threadIndex][posMCM]->SetModelVector(input);
255 m_ReferenceInputWeights[threadIndex][posMCM] = overlap;
257 unsigned int numEffectiveAnisotropicCompartments = 0;
258 for (
unsigned int i = numIsoCompartments;i < numberOfTotalInputCompartments;++i)
260 double fascWeight = m_ReferenceInputModels[threadIndex][posMCM]->GetCompartmentWeight(i);
264 ++numEffectiveAnisotropicCompartments;
267 if (numEffectiveAnisotropicCompartments > maxNumCompartments)
268 maxNumCompartments = numEffectiveAnisotropicCompartments;
270 totalOverlap += overlap;
275 if (totalOverlap < 0.5)
277 this->UnlockWorkIndex(threadIndex);
278 voxelOutputValue.Fill(0.0);
279 return voxelOutputValue;
282 m_MCMAveragers[threadIndex]->SetNumberOfOutputDirectionalCompartments(maxNumCompartments);
283 m_MCMAveragers[threadIndex]->SetInputModels(m_ReferenceInputModels[threadIndex]);
284 m_MCMAveragers[threadIndex]->SetInputWeights(m_ReferenceInputWeights[threadIndex]);
286 m_MCMAveragers[threadIndex]->Update();
288 voxelOutputValue = m_MCMAveragers[threadIndex]->GetOutputModel()->GetModelVector();
290 this->UnlockWorkIndex(threadIndex);
293 for (
int i = 0; i < voxelOutputValue.GetSize(); ++i)
295 if (std::isnan(voxelOutputValue[i]))
296 itkExceptionMacro(
"Problem, OutputVoxel has a nan value.");
299 return voxelOutputValue;
Superclass::OutputType OutputType
TInputImage::PixelType PixelType
Superclass::IndexType IndexType
void TestModelsAdequation(MCModelPointer &inputModel, MCModelPointer &outputModel)
Tests if input and output models of the interpolator are compatible.
void UnlockWorkIndex(unsigned int index) const
Superclass::ContinuousIndexType ContinuousIndexType
virtual void SetInputImage(const InputImageType *ptr) ITK_OVERRIDE
virtual OutputType EvaluateAtContinuousIndex(const ContinuousIndexType &index) const ITK_OVERRIDE
MCModelType::Pointer MCModelPointer
MCMLinearInterpolateImageFunction()
void SetReferenceOutputModel(MCModelPointer &model)
Superclass::InputImageType InputImageType
virtual void ResetAveragePointers(MCModelPointer &model)
Resets averager pointers, can be overloaded to handle more models.
virtual bool CheckModelCompatibility(MCModelPointer &model)
Check if model can actually be interpolated.
unsigned int GetFreeWorkIndex() const