Medical Imaging Interaction Toolkit  2018.4.99-12ad79a3
Medical Imaging Interaction Toolkit
itkMultiOutputNaryFunctorImageFilter.tpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #ifndef __itkMultiOutputNaryFunctorImageFilter_hxx
14 #define __itkMultiOutputNaryFunctorImageFilter_hxx
15 
16 #include "itkMultiOutputNaryFunctorImageFilter.h"
17 #include "itkImageRegionIterator.h"
18 #include "itkProgressReporter.h"
19 
20 namespace itk
21 {
22  /**
23  * Constructor
24  */
25  template< class TInputImage, class TOutputImage, class TFunction, class TMaskImage >
26  MultiOutputNaryFunctorImageFilter< TInputImage, TOutputImage, TFunction, TMaskImage >
27  ::MultiOutputNaryFunctorImageFilter()
28  {
29  // This number will be incremented each time an image
30  // is added over the two minimum required
31  this->SetNumberOfRequiredInputs(1);
32 
33  this->ActualizeOutputs();
34  }
35 
36  template< class TInputImage, class TOutputImage, class TFunction, class TMaskImage >
37  void
38  MultiOutputNaryFunctorImageFilter< TInputImage, TOutputImage, TFunction, TMaskImage >
39  ::ActualizeOutputs()
40  {
41  this->SetNumberOfRequiredOutputs(m_Functor.GetNumberOfOutputs());
42 
43  for (typename Superclass::DataObjectPointerArraySizeType i = this->GetNumberOfIndexedOutputs(); i< m_Functor.GetNumberOfOutputs(); ++i)
44  {
45  this->SetNthOutput( i, this->MakeOutput(i) );
46  }
47 
48  while(this->GetNumberOfIndexedOutputs() > m_Functor.GetNumberOfOutputs())
49  {
50  this->RemoveOutput(this->GetNumberOfIndexedOutputs()-1);
51  }
52  };
53 
54  /**
55  * ThreadedGenerateData Performs the pixel-wise addition
56  */
57  template< class TInputImage, class TOutputImage, class TFunction, class TMaskImage >
58  void
59  MultiOutputNaryFunctorImageFilter< TInputImage, TOutputImage, TFunction, TMaskImage >
60  ::ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,
61  ThreadIdType threadId)
62  {
63  ProgressReporter progress( this, threadId,
64  outputRegionForThread.GetNumberOfPixels() );
65 
66  const unsigned int numberOfInputImages =
67  static_cast< unsigned int >( this->GetNumberOfIndexedInputs() );
68 
69  const unsigned int numberOfOutputImages =
70  static_cast< unsigned int >( this->GetNumberOfIndexedOutputs() );
71 
72  typedef ImageRegionConstIterator< TInputImage > ImageRegionConstIteratorType;
73  std::vector< ImageRegionConstIteratorType * > inputItrVector;
74  inputItrVector.reserve(numberOfInputImages);
75 
76  typedef ImageRegionIterator< TOutputImage > OutputImageRegionIteratorType;
77  std::vector< OutputImageRegionIteratorType * > outputItrVector;
78  outputItrVector.reserve(numberOfOutputImages);
79 
80  //check if mask image is set and generate iterator if mask is valid
81  typedef ImageRegionConstIterator< TMaskImage > MaskImageRegionIteratorType;
82  MaskImageRegionIteratorType* pMaskIterator = nullptr;
83 
84  if (m_Mask.IsNotNull())
85  {
86  if (!m_Mask->GetLargestPossibleRegion().IsInside(outputRegionForThread))
87  {
88  itkExceptionMacro("Mask of filter is set but does not cover region of thread. Mask region: "<< m_Mask->GetLargestPossibleRegion() <<"Thread region: "<<outputRegionForThread)
89  }
90  pMaskIterator = new MaskImageRegionIteratorType(m_Mask,outputRegionForThread);
91  }
92 
93  // go through the inputs and add iterators for non-null inputs
94  for ( unsigned int i = 0; i < numberOfInputImages; ++i )
95  {
96  InputImagePointer inputPtr =
97  dynamic_cast< TInputImage * >( ProcessObject::GetInput(i) );
98 
99  if ( inputPtr )
100  {
101  inputItrVector.push_back( new ImageRegionConstIteratorType(inputPtr, outputRegionForThread) );
102  }
103 
104  }
105 
106  // go through the outputs and add iterators for non-null outputs
107  for ( unsigned int i = 0; i < numberOfOutputImages; ++i )
108  {
109  OutputImagePointer outputPtr =
110  dynamic_cast< TOutputImage * >( ProcessObject::GetOutput(i) );
111 
112  if ( outputPtr )
113  {
114  outputItrVector.push_back( new OutputImageRegionIteratorType(outputPtr, outputRegionForThread) );
115  }
116  }
117 
118  typename std::vector< ImageRegionConstIteratorType * >::iterator regionInputIterators;
119  const typename std::vector< ImageRegionConstIteratorType * >::const_iterator regionInputItEnd =
120  inputItrVector.end();
121 
122  typename std::vector< OutputImageRegionIteratorType * >::iterator regionOutputIterators;
123  const typename std::vector< OutputImageRegionIteratorType * >::const_iterator regionOutputItEnd =
124  outputItrVector.end();
125 
126  const unsigned int numberOfValidInputImages = inputItrVector.size();
127  const unsigned int numberOfValidOutputImages = outputItrVector.size();
128 
129  if ( (numberOfValidInputImages != 0) && ( numberOfValidOutputImages != 0))
130  {
131  try
132  {
133 
134  while ( !(outputItrVector.front()->IsAtEnd()) )
135  {
136  typename NaryInputArrayType::iterator arrayInIt;
137  typename NaryOutputArrayType::iterator arrayOutIt;
138  NaryInputArrayType naryInputArray(numberOfValidInputImages);
139  NaryOutputArrayType naryOutputArray(numberOfValidOutputImages);
140 
141  bool isValid = true;
142 
143  if (pMaskIterator)
144  {
145  isValid = pMaskIterator->Get() > 0;
146  ++(*pMaskIterator);
147  }
148 
149  arrayInIt = naryInputArray.begin();
150  regionInputIterators = inputItrVector.begin();
151 
152  typename ImageRegionConstIteratorType::IndexType currentIndex;
153  if(regionInputIterators != regionInputItEnd)
154  {
155  currentIndex = ( *regionInputIterators )->GetIndex();
156  }
157 
158  while ( regionInputIterators != regionInputItEnd )
159  {
160  *arrayInIt++ = ( *regionInputIterators )->Get();
161  ++( *( *regionInputIterators ) );
162  ++regionInputIterators;
163  }
164 
165  if (isValid)
166  {
167  naryOutputArray = m_Functor(naryInputArray, currentIndex);
168 
169  if (numberOfValidOutputImages != naryOutputArray.size())
170  {
171  itkExceptionMacro("Error. Number of valid output images do not equal number of outputs required by functor. Number of valid outputs: "<< numberOfValidOutputImages << "; needed output number:" << this->m_Functor.GetNumberOfOutputs());
172  }
173  }
174  else
175  {
176  for (typename NaryOutputArrayType::iterator pos = naryOutputArray.begin(); pos!= naryOutputArray.end(); ++pos)
177  {
178  *pos = 0.0;
179  }
180  }
181 
182  arrayOutIt = naryOutputArray.begin();
183  regionOutputIterators = outputItrVector.begin();
184  while ( regionOutputIterators != regionOutputItEnd )
185  {
186  ( *regionOutputIterators )->Set(*arrayOutIt++);
187  ++( *( *regionOutputIterators ) );
188  ++regionOutputIterators;
189  }
190 
191  progress.CompletedPixel();
192  }
193  }
194  catch(...)
195  {
196  // Free memory in case of exceptions
197  regionInputIterators = inputItrVector.begin();
198  while ( regionInputIterators != regionInputItEnd )
199  {
200  delete ( *regionInputIterators++ );
201  }
202 
203  regionOutputIterators = outputItrVector.begin();
204  while ( regionOutputIterators != regionOutputItEnd )
205  {
206  delete ( *regionOutputIterators++ );
207  }
208 
209  delete pMaskIterator;
210  throw;
211  }
212  }
213 
214  // Free memory regulary
215  regionInputIterators = inputItrVector.begin();
216  while ( regionInputIterators != regionInputItEnd )
217  {
218  delete ( *regionInputIterators++ );
219  }
220 
221  regionOutputIterators = outputItrVector.begin();
222  while ( regionOutputIterators != regionOutputItEnd )
223  {
224  delete ( *regionOutputIterators++ );
225  }
226 
227  delete pMaskIterator;
228  }
229 } // end namespace itk
230 
231 #endif