File: itkFiniteDifferenceSparseImageFilter.txx

package info (click to toggle)
insighttoolkit 3.6.0-3
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 94,956 kB
  • ctags: 74,981
  • sloc: cpp: 355,621; ansic: 195,070; fortran: 28,713; python: 3,802; tcl: 1,996; sh: 1,175; java: 583; makefile: 415; csh: 184; perl: 175
file content (337 lines) | stat: -rw-r--r-- 12,173 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkFiniteDifferenceSparseImageFilter.txx,v $
  Language:  C++
  Date:      $Date: 2008-01-07 13:33:59 $
  Version:   $Revision: 1.5 $

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

     =========================================================================*/
#ifndef __itkFiniteDifferenceSparseImageFilter_txx_
#define __itkFiniteDifferenceSparseImageFilter_txx_ 

#include "itkFiniteDifferenceSparseImageFilter.h"

namespace itk {

template <class TInputImageType, class TSparseOutputImageType>
FiniteDifferenceSparseImageFilter <TInputImageType, TSparseOutputImageType>
::FiniteDifferenceSparseImageFilter()
{
  m_SparseFunction = 0;
  m_PrecomputeFlag = false;
}

template <class TInputImageType, class TSparseOutputImageType>
void
FiniteDifferenceSparseImageFilter <TInputImageType, TSparseOutputImageType>
::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
  os << indent << "PrecomputeFlag: " << m_PrecomputeFlag << std::endl;
}

template <class TInputImageType, class TSparseOutputImageType>
void
FiniteDifferenceSparseImageFilter <TInputImageType, TSparseOutputImageType>
::SetSparseFunction( SparseFunctionType *sf )
{
  m_SparseFunction = sf;
  Superclass::SetDifferenceFunction (sf);
}

template <class TInputImageType, class TSparseOutputImageType>
void
FiniteDifferenceSparseImageFilter <TInputImageType, TSparseOutputImageType>
::Initialize()
{
  m_RegionList=(this->GetOutput()->GetNodeList())
    ->SplitRegions(this->GetNumberOfThreads());
  // The active set of pixels in the sparse image is split into multi-threading
  // regions once here for computationally efficiency.
  // Later GetSplitRegions is used to access these partitions. 
  // This assumes that the active will not be changed until another
  // call to Initialize(). Any reinitialization function also must call the
  // SplitRegions function.
}

template <class TInputImageType, class TSparseOutputImageType>
int 
FiniteDifferenceSparseImageFilter<TInputImageType, TSparseOutputImageType>
::GetSplitRegion( int i, int num, ThreadRegionType &splitRegion ) 
{
  splitRegion.first = m_RegionList[i].first;
  splitRegion.last = m_RegionList[i].last;
  return num;
  // check this last line with the ITKdevelopers. not sure what this is doing
  // copied it from FiniteDifferenceImageFilter class
}

template<class TInputImageType, class TSparseOutputImageType>
void
FiniteDifferenceSparseImageFilter<TInputImageType, TSparseOutputImageType>
::ApplyUpdate( TimeStepType dt )
{
  // Set up for multithreaded processing.
  FDThreadStruct str;
  str.Filter = this;
  str.TimeStep = dt;
  this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
  this->GetMultiThreader()->SetSingleMethod(this->ApplyUpdateThreaderCallback,
                                            &str);
  // Multithread the execution
  this->GetMultiThreader()->SingleMethodExecute();
}
 
template<class TInputImageType, class TSparseOutputImageType>
ITK_THREAD_RETURN_TYPE
FiniteDifferenceSparseImageFilter<TInputImageType, TSparseOutputImageType>
::ApplyUpdateThreaderCallback( void * arg )
{
  FDThreadStruct * str;
  int total, threadId, threadCount;

  threadId = ((MultiThreader::ThreadInfoStruct *)(arg))->ThreadID;
  threadCount = ((MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads;
  str = (FDThreadStruct *)
    (((MultiThreader::ThreadInfoStruct *)(arg))->UserData);

  // Execute the actual method with appropriate output region
  // first find out how many pieces extent can be split into.
  // Use GetSplitRegion to access partition previously computed by
  // the SplitRegions function in the SparseFieldLayer class.
  ThreadRegionType splitRegion;
  total = str->Filter->GetSplitRegion(threadId, threadCount, splitRegion);
  
  if (threadId < total)
    {
      str->Filter->ThreadedApplyUpdate(str->TimeStep, splitRegion, threadId);
    }

  return ITK_THREAD_RETURN_VALUE;
}

template <class TInputImageType, class TSparseOutputImageType>
void
FiniteDifferenceSparseImageFilter<TInputImageType, TSparseOutputImageType>
::ThreadedApplyUpdate( TimeStepType dt, const ThreadRegionType &regionToProcess,
                       int)
{
  typename NodeListType::Iterator it;
  
  for (it=regionToProcess.first; it != regionToProcess.last; ++it)
    {
    // all sparse image node types must have Data and Update members to be used
    // with this filter 
    it->m_Data = this->DataConstraint (it->m_Data +
                                       it->m_Update * dt);
    }
}

template <class TInputImageType, class TSparseOutputImageType>
void
FiniteDifferenceSparseImageFilter<TInputImageType, TSparseOutputImageType>
::PrecalculateChange()
{
  // Set up for multithreaded processing.
  FDThreadStruct str;
  str.Filter = this;
  
  this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
  this->GetMultiThreader()->SetSingleMethod
    (this->PrecalculateChangeThreaderCallback,&str);
  
  // Multithread the execution
  this->GetMultiThreader()->SingleMethodExecute();
}

template <class TInputImageType, class TSparseOutputImageType>
typename FiniteDifferenceSparseImageFilter <TInputImageType,
                                            TSparseOutputImageType>::TimeStepType
FiniteDifferenceSparseImageFilter<TInputImageType, TSparseOutputImageType>
::CalculateChange()
{
  if (m_PrecomputeFlag == true)
    {
    this->PrecalculateChange();
    }
  int threadCount;
  TimeStepType dt;

  // Set up for multithreaded processing.
  FDThreadStruct str;
  str.Filter = this;
  str.TimeStep = NumericTraits<TimeStepType>::Zero;
  // Not used during the calculate change step for normals. 

  this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
  this->GetMultiThreader()->SetSingleMethod
    (this->CalculateChangeThreaderCallback,&str);

  // Initialize the list of time step values that will be generated by the
  // various threads.  There is one distinct slot for each possible thread,
  // so this data structure is thread-safe.  All of the time steps calculated
  // in each thread will be combined in the ResolveTimeStepMethod.
  threadCount = this->GetMultiThreader()->GetNumberOfThreads();  
  str.TimeStepList = new TimeStepType[threadCount];                 
  str.ValidTimeStepList = new bool[threadCount];
  for (int i =0; i < threadCount; ++i)
    {
    str.ValidTimeStepList[i] = false;
    } 

  // Multithread the execution
  this->GetMultiThreader()->SingleMethodExecute();

  // Resolve the single value time step to return.  The default implementation
  // of ResolveTimeStep is to return the lowest value in the list that it is
  // given.  
  dt = this->ResolveTimeStep(str.TimeStepList,
                             str.ValidTimeStepList, threadCount);
  
  delete [] str.TimeStepList;
  delete [] str.ValidTimeStepList;

  return  dt;
}

template <class TInputImageType, class TSparseOutputImageType>
ITK_THREAD_RETURN_TYPE
FiniteDifferenceSparseImageFilter<TInputImageType, TSparseOutputImageType>
::CalculateChangeThreaderCallback( void * arg )
{
  FDThreadStruct * str;
  int total, threadId, threadCount;

  threadId = ((MultiThreader::ThreadInfoStruct *)(arg))->ThreadID;
  threadCount = ((MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads;
  
  str = (FDThreadStruct *)
    (((MultiThreader::ThreadInfoStruct *)(arg))->UserData);

  // Execute the actual method with appropriate output region
  // first find out how many pieces extent can be split into.
  // Use GetSplitRegion to access partition previously computed by
  // the Splitegions function in the SparseFieldLayer class.
  ThreadRegionType splitRegion;
  total = str->Filter->GetSplitRegion(threadId, threadCount, splitRegion);
  
  if (threadId < total)
    { 
      str->TimeStepList[threadId]
        = str->Filter->ThreadedCalculateChange(splitRegion, threadId);
      str->ValidTimeStepList[threadId] = true;
    }

  return ITK_THREAD_RETURN_VALUE;  
}

template <class TInputImageType, class TSparseOutputImageType>
ITK_THREAD_RETURN_TYPE
FiniteDifferenceSparseImageFilter<TInputImageType, TSparseOutputImageType>
::PrecalculateChangeThreaderCallback( void * arg )
{
  FDThreadStruct * str;
  int total, threadId, threadCount;

  threadId = ((MultiThreader::ThreadInfoStruct *)(arg))->ThreadID;
  threadCount = ((MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads;
  
  str = (FDThreadStruct *)
    (((MultiThreader::ThreadInfoStruct *)(arg))->UserData);

  // Execute the actual method with appropriate output region
  // first find out how many pieces extent can be split into.
  // Use GetSplitRegion to access partition previously computed by
  // the Splitegions function in the SparseFieldLayer class.
  ThreadRegionType splitRegion;
  total = str->Filter->GetSplitRegion(threadId, threadCount, splitRegion);
  
  if (threadId < total)
    { 
    str->Filter->ThreadedPrecalculateChange(splitRegion, threadId);
    }

  return ITK_THREAD_RETURN_VALUE;  
}

template <class TInputImageType, class TSparseOutputImageType>
typename FiniteDifferenceSparseImageFilter<TInputImageType,
                                           TSparseOutputImageType>::TimeStepType
FiniteDifferenceSparseImageFilter<TInputImageType, TSparseOutputImageType>
::ThreadedCalculateChange( const ThreadRegionType &regionToProcess, int )
{
  typedef typename FiniteDifferenceFunctionType::NeighborhoodType
    NeighborhoodIteratorType;
  
  typename SparseOutputImageType::Pointer output = this->GetOutput();

  TimeStepType timeStep;
  void *globalData;

  const SizeType  radius = m_SparseFunction->GetRadius();
  
  // Ask the function object for a pointer to a data structure it will use to
  // manage any global values it needs.  We'll pass this back to the function
  // object at each calculation so that the function object can use it to
  // determine a time step for this iteration.
  globalData = m_SparseFunction->GetGlobalDataPointer();
  
  typename NodeListType::Iterator bandIt;
  NeighborhoodIteratorType outputIt(radius, output,
                                    output->GetRequestedRegion());

  // compute the update variables
  for (bandIt = regionToProcess.first; bandIt != regionToProcess.last; ++bandIt)
    {
    outputIt.SetLocation (bandIt->m_Index);
    outputIt.GetCenterPixel()->m_Update =
      m_SparseFunction->ComputeSparseUpdate(outputIt, globalData);
    }
  
  // Ask the finite difference function to compute the time step for
  // this iteration.  We give it the global data pointer to use, then
  // ask it to free the global data memory. 
  timeStep = m_SparseFunction->ComputeGlobalTimeStep(globalData);
  m_SparseFunction->ReleaseGlobalDataPointer(globalData);

  return timeStep;
}

template <class TInputImageType, class TSparseOutputImageType>
void
FiniteDifferenceSparseImageFilter<TInputImageType, TSparseOutputImageType>
::ThreadedPrecalculateChange( const ThreadRegionType &regionToProcess, int )
{
  typedef typename FiniteDifferenceFunctionType::NeighborhoodType
    NeighborhoodIteratorType;

  typename SparseOutputImageType::Pointer output = this->GetOutput();

  const SizeType  radius = m_SparseFunction->GetRadius();
  
  typename NodeListType::Iterator bandIt;
  NeighborhoodIteratorType outputIt(radius, output,
                                    output->GetRequestedRegion());

  // the step for computing the flux variables
  // these are used for computing the update in diffusion processes
  // can disable these lines for non-diffusion processes
  for (bandIt = regionToProcess.first; bandIt != regionToProcess.last; ++bandIt)
    {
    outputIt.SetLocation(bandIt->m_Index);
    m_SparseFunction->PrecomputeSparseUpdate(outputIt);
    }

}

} // end namespace itk

#endif