Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 /*=========================================================================
17 
18 Program: Tensor ToolKit - TTK
19 Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx $
20 Language: C++
21 Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
22 Version: $Revision: 68 $
23 
24 Copyright (c) INRIA 2010. All rights reserved.
25 See LICENSE.txt for details.
26 
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.
30 
31 =========================================================================*/
32 #ifndef _itk_ElectrostaticRepulsionDiffusionGradientReductionFilter_txx_
33 #define _itk_ElectrostaticRepulsionDiffusionGradientReductionFilter_txx_
34 #endif
35 
36 #define _USE_MATH_DEFINES
37 
38 #include "itkElectrostaticRepulsionDiffusionGradientReductionFilter.h"
39 #include <math.h>
40 #include <time.h>
41 #include <itkImageRegionIterator.h>
42 #include <itkImageRegion.h>
43 
44 namespace itk
45 {
46 
47 template <class TInputScalarType, class TOutputScalarType>
48 ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
49 ::ElectrostaticRepulsionDiffusionGradientReductionFilter()
50 {
51  this->SetNumberOfRequiredInputs( 1 );
52 }
53 
54 template <class TInputScalarType, class TOutputScalarType>
55 double
56 ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
57 ::Costs()
58 {
59  double costs = 2*M_PI;
60  for (IndicesVector::iterator it = m_UsedGradientIndices.begin(); it!=m_UsedGradientIndices.end(); ++it)
61  {
62  for (IndicesVector::iterator it2 = m_UsedGradientIndices.begin(); it2!=m_UsedGradientIndices.end(); ++it2)
63  if (it != it2)
64  {
65  vnl_vector_fixed<double,3> v1 = m_OriginalGradientDirections->at(*it);
66  vnl_vector_fixed<double,3> v2 = m_OriginalGradientDirections->at(*it2);
67 
68  v1.normalize(); v2.normalize();
69  double temp = dot_product(v1,v2);
70  if (temp>1)
71  temp = 1;
72  else if (temp<-1)
73  temp = -1;
74 
75  double angle = acos(temp);
76 
77  if (angle<costs)
78  costs = angle;
79 
80  temp = dot_product(-v1,v2);
81  if (temp>1)
82  temp = 1;
83  else if (temp<-1)
84  temp = -1;
85 
86  angle = acos(temp);
87  if (angle<costs)
88  costs = angle;
89  }
90  }
91 
92  return costs;
93 }
94 
95 template <class TInputScalarType, class TOutputScalarType>
96 void
97 ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
98 ::GenerateData()
99 {
100  unsigned int randSeed = time(NULL);
101 
102  if(m_InputBValueMap.empty() || m_NumGradientDirections.size()!=m_InputBValueMap.size())
103  return;
104 
105  BValueMap manipulatedMap = m_InputBValueMap;
106 
107  int shellCounter = 0;
108  for(BValueMap::iterator it = m_InputBValueMap.begin(); it != m_InputBValueMap.end(); it++ )
109  {
110  srand(randSeed);
111 
112  // initialize index vectors
113  m_UsedGradientIndices.clear();
114  m_UnusedGradientIndices.clear();
115 
116  if ( it->second.size() <= m_NumGradientDirections[shellCounter] )
117  {
118  itkWarningMacro( << "current directions: " << it->second.size() << " wanted directions: " << m_NumGradientDirections[shellCounter]);
119  m_NumGradientDirections[shellCounter] = it->second.size();
120  shellCounter++;
121  continue;
122  }
123  MITK_INFO << "Shell number: " << shellCounter;
124 
125  unsigned int c=0;
126 
127  for (unsigned int i=0; i<it->second.size(); i++)
128  {
129  if (c<m_NumGradientDirections[shellCounter])
130  m_UsedGradientIndices.push_back(it->second.at(i));
131  else
132  m_UnusedGradientIndices.push_back(it->second.at(i));
133  c++;
134  }
135 
136  double minAngle = Costs();
137  double newMinAngle = 0;
138 
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;
145  int iUsed = 0;
146  if (m_UsedGradientIndices.size()>0)
147  while ( stagnationCount<1000 && rejectionCount<maxRejections )
148  {
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;
156 
157  newMinAngle = Costs(); // calculate costs of proposed configuration
158  if (newMinAngle > minAngle) // accept or reject proposal
159  {
160  MITK_INFO << "minimum angle: " << 180*newMinAngle/M_PI;
161 
162  if ( (newMinAngle-minAngle)<0.01 )
163  stagnationCount++;
164  else
165  stagnationCount = 0;
166 
167  minAngle = newMinAngle;
168  rejectionCount = 0;
169  }
170  else
171  {
172  rejectionCount++;
173  m_UsedGradientIndices.at(iUsed) = vUsed;
174  m_UnusedGradientIndices.at(iUnUsed) = vUnUsed;
175  }
176  iUsed++;
177  iUsed = iUsed % m_UsedGradientIndices.size();
178  }
179  manipulatedMap[it->first] = m_UsedGradientIndices;
180  shellCounter++;
181  }
182 
183  int vecLength = 0 ;
184  for(BValueMap::iterator it = manipulatedMap.begin(); it != manipulatedMap.end(); it++)
185  vecLength += it->second.size();
186 
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();
197 
198  itk::ImageRegionIterator< OutputImageType > newIt(outImage, outImage->GetLargestPossibleRegion());
199  newIt.GoToBegin();
200 
201  typename InputImageType::Pointer inImage = const_cast<InputImageType*>(this->GetInput(0));
202  itk::ImageRegionIterator< InputImageType > oldIt(inImage, inImage->GetLargestPossibleRegion());
203  oldIt.GoToBegin();
204 
205  // initial new value of voxel
206  OutputPixelType newVec;
207  newVec.SetSize( vecLength );
208  newVec.AllocateElements( vecLength );
209 
210  // generate new pixel values
211  while(!newIt.IsAtEnd())
212  {
213  // init new vector with zeros
214  newVec.Fill(0.0);
215  InputPixelType oldVec = oldIt.Get();
216 
217  int index = 0;
218  for(BValueMap::iterator it=manipulatedMap.begin(); it!=manipulatedMap.end(); it++)
219  for(unsigned int j=0; j<it->second.size(); j++)
220  {
221  newVec[index] = oldVec[it->second.at(j)];
222  index++;
223  }
224  newIt.Set(newVec);
225 
226  ++newIt;
227  ++oldIt;
228  }
229 
230  // set new gradient directions
231  m_GradientDirections = GradientDirectionContainerType::New();
232  int index = 0;
233  for(BValueMap::iterator it = manipulatedMap.begin(); it != manipulatedMap.end(); it++)
234  for(unsigned int j = 0; j < it->second.size(); j++)
235  {
236  m_GradientDirections->InsertElement(index, m_OriginalGradientDirections->at(it->second.at(j)));
237  index++;
238  }
239 
240  this->SetNumberOfRequiredOutputs (1);
241  this->SetNthOutput (0, outImage);
242  MITK_INFO << "...done";
243 }
244 
245 template <class TInputScalarType, class TOutputScalarType>
246 void
247 ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
248 ::UpdateOutputInformation()
249 {
250  Superclass::UpdateOutputInformation();
251 
252  int vecLength = 0 ;
253  for(unsigned int index = 0; index < m_NumGradientDirections.size(); index++)
254  {
255  vecLength += m_NumGradientDirections[index];
256  }
257 
258  this->GetOutput()->SetVectorLength( vecLength );
259 }
260 
261 } // end of namespace