1 /*===================================================================
3 The Medical Imaging Interaction Toolkit (MITK)
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 See LICENSE.txt or http://www.mitk.org for details.
15 ===================================================================*/
16 /*=========================================================================
18 Program: Tensor ToolKit - TTK
19 Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx $
21 Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
22 Version: $Revision: 68 $
24 Copyright (c) INRIA 2010. All rights reserved.
25 See LICENSE.txt for details.
27 This software is distributed WITHOUT ANY WARRANTY; without even
28 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
29 PURPOSE. See the above copyright notices for more information.
31 =========================================================================*/
32 #ifndef _itk_ElectrostaticRepulsionDiffusionGradientReductionFilter_txx_
33 #define _itk_ElectrostaticRepulsionDiffusionGradientReductionFilter_txx_
36 #define _USE_MATH_DEFINES
38 #include "itkElectrostaticRepulsionDiffusionGradientReductionFilter.h"
41 #include <itkImageRegionIterator.h>
42 #include <itkImageRegion.h>
47 template <class TInputScalarType, class TOutputScalarType>
48 ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
49 ::ElectrostaticRepulsionDiffusionGradientReductionFilter()
51 this->SetNumberOfRequiredInputs( 1 );
54 template <class TInputScalarType, class TOutputScalarType>
56 ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
59 double costs = 2*M_PI;
60 for (IndicesVector::iterator it = m_UsedGradientIndices.begin(); it!=m_UsedGradientIndices.end(); ++it)
62 for (IndicesVector::iterator it2 = m_UsedGradientIndices.begin(); it2!=m_UsedGradientIndices.end(); ++it2)
65 vnl_vector_fixed<double,3> v1 = m_OriginalGradientDirections->at(*it);
66 vnl_vector_fixed<double,3> v2 = m_OriginalGradientDirections->at(*it2);
68 v1.normalize(); v2.normalize();
69 double temp = dot_product(v1,v2);
75 double angle = acos(temp);
80 temp = dot_product(-v1,v2);
95 template <class TInputScalarType, class TOutputScalarType>
97 ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
100 unsigned int randSeed = time(NULL);
102 if(m_InputBValueMap.empty() || m_NumGradientDirections.size()!=m_InputBValueMap.size())
105 BValueMap manipulatedMap = m_InputBValueMap;
107 int shellCounter = 0;
108 for(BValueMap::iterator it = m_InputBValueMap.begin(); it != m_InputBValueMap.end(); it++ )
112 // initialize index vectors
113 m_UsedGradientIndices.clear();
114 m_UnusedGradientIndices.clear();
116 if ( it->second.size() <= m_NumGradientDirections[shellCounter] )
118 itkWarningMacro( << "current directions: " << it->second.size() << " wanted directions: " << m_NumGradientDirections[shellCounter]);
119 m_NumGradientDirections[shellCounter] = it->second.size();
123 MITK_INFO << "Shell number: " << shellCounter;
127 for (unsigned int i=0; i<it->second.size(); i++)
129 if (c<m_NumGradientDirections[shellCounter])
130 m_UsedGradientIndices.push_back(it->second.at(i));
132 m_UnusedGradientIndices.push_back(it->second.at(i));
136 double minAngle = Costs();
137 double newMinAngle = 0;
139 MITK_INFO << "minimum angle: " << 180*minAngle/M_PI;
140 int stagnationCount = 0;
141 int rejectionCount = 0;
142 int maxRejections = m_NumGradientDirections[shellCounter] * 1000;
143 if (maxRejections<10000)
144 maxRejections = 10000;
146 if (m_UsedGradientIndices.size()>0)
147 while ( stagnationCount<1000 && rejectionCount<maxRejections )
149 // make proposal for new gradient configuration by randomly removing one of the currently used directions and instead adding one of the unused directions
150 //int iUsed = rand() % m_UsedGradientIndices.size();
151 int iUnUsed = rand() % m_UnusedGradientIndices.size();
152 int vUsed = m_UsedGradientIndices.at(iUsed);
153 int vUnUsed = m_UnusedGradientIndices.at(iUnUsed);
154 m_UsedGradientIndices.at(iUsed) = vUnUsed;
155 m_UnusedGradientIndices.at(iUnUsed) = vUsed;
157 newMinAngle = Costs(); // calculate costs of proposed configuration
158 if (newMinAngle > minAngle) // accept or reject proposal
160 MITK_INFO << "minimum angle: " << 180*newMinAngle/M_PI;
162 if ( (newMinAngle-minAngle)<0.01 )
167 minAngle = newMinAngle;
173 m_UsedGradientIndices.at(iUsed) = vUsed;
174 m_UnusedGradientIndices.at(iUnUsed) = vUnUsed;
177 iUsed = iUsed % m_UsedGradientIndices.size();
179 manipulatedMap[it->first] = m_UsedGradientIndices;
184 for(BValueMap::iterator it = manipulatedMap.begin(); it != manipulatedMap.end(); it++)
185 vecLength += it->second.size();
187 // initialize output image
188 typename OutputImageType::Pointer outImage = OutputImageType::New();
189 outImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing
190 outImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin
191 outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction
192 outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
193 outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
194 outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
195 outImage->SetVectorLength( vecLength ); // Set the vector length
196 outImage->Allocate();
198 itk::ImageRegionIterator< OutputImageType > newIt(outImage, outImage->GetLargestPossibleRegion());
201 typename InputImageType::Pointer inImage = const_cast<InputImageType*>(this->GetInput(0));
202 itk::ImageRegionIterator< InputImageType > oldIt(inImage, inImage->GetLargestPossibleRegion());
205 // initial new value of voxel
206 OutputPixelType newVec;
207 newVec.SetSize( vecLength );
208 newVec.AllocateElements( vecLength );
210 // generate new pixel values
211 while(!newIt.IsAtEnd())
213 // init new vector with zeros
215 InputPixelType oldVec = oldIt.Get();
218 for(BValueMap::iterator it=manipulatedMap.begin(); it!=manipulatedMap.end(); it++)
219 for(unsigned int j=0; j<it->second.size(); j++)
221 newVec[index] = oldVec[it->second.at(j)];
230 // set new gradient directions
231 m_GradientDirections = GradientDirectionContainerType::New();
233 for(BValueMap::iterator it = manipulatedMap.begin(); it != manipulatedMap.end(); it++)
234 for(unsigned int j = 0; j < it->second.size(); j++)
236 m_GradientDirections->InsertElement(index, m_OriginalGradientDirections->at(it->second.at(j)));
240 this->SetNumberOfRequiredOutputs (1);
241 this->SetNthOutput (0, outImage);
242 MITK_INFO << "...done";
245 template <class TInputScalarType, class TOutputScalarType>
247 ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
248 ::UpdateOutputInformation()
250 Superclass::UpdateOutputInformation();
253 for(unsigned int index = 0; index < m_NumGradientDirections.size(); index++)
255 vecLength += m_NumGradientDirections[index];
258 this->GetOutput()->SetVectorLength( vecLength );
261 } // end of namespace