1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 
19 #ifndef itkLevelSetEquationTermContainer_h
20 #define itkLevelSetEquationTermContainer_h
21 
22 #include "itkLevelSetEquationTermBase.h"
23 #include "itkObject.h"
24 
25 #include <unordered_map>
26 
27 #include <map>
28 #include <string>
29 
30 namespace itk
31 {
32 /**
33  *  \class LevelSetEquationTermContainer
34  *  \brief Class for container holding the terms of a given level set update equation
35  *
36  *  \tparam TInputImage Input image or speed image or feature image for segmentation
37  *  \tparam TLevelSetContainer Container holding the all the level set functions
38  *
39  *  \ingroup ITKLevelSetsv4
40  */
41 template< typename TInputImage,
42           typename TLevelSetContainer >
43 class ITK_TEMPLATE_EXPORT LevelSetEquationTermContainer : public Object
44 {
45 public:
46   ITK_DISALLOW_COPY_AND_ASSIGN(LevelSetEquationTermContainer);
47 
48   using Self = LevelSetEquationTermContainer;
49   using Pointer = SmartPointer< Self >;
50   using ConstPointer = SmartPointer< const Self >;
51   using Superclass = Object;
52 
53   /** Method for creation through object factory */
54   itkNewMacro( Self );
55 
56   /** Run-time type information */
57   itkTypeMacro( LevelSetEquationTermContainer,
58                 Object );
59 
60   using TermIdType = unsigned int;
61 
62   using InputImageType = TInputImage;
63   using InputImagePointer = typename InputImageType::Pointer;
64 
65   using LevelSetContainerType = TLevelSetContainer;
66   using LevelSetContainerPointer = typename LevelSetContainerType::Pointer;
67 
68   using LevelSetType = typename LevelSetContainerType::LevelSetType;
69   using LevelSetPointer = typename LevelSetContainerType::LevelSetPointer;
70 
71   using LevelSetIdentifierType = typename LevelSetContainerType::LevelSetIdentifierType;
72   using LevelSetOutputPixelType = typename LevelSetContainerType::OutputType;
73   using LevelSetOutputRealType = typename LevelSetContainerType::OutputRealType;
74   using LevelSetDataType = typename LevelSetContainerType::LevelSetDataType;
75   using LevelSetInputIndexType = typename LevelSetContainerType::InputIndexType;
76   using LevelSetGradientType = typename LevelSetContainerType::GradientType;
77   using LevelSetHessianType = typename LevelSetContainerType::HessianType;
78 
79   using TermType =
80       LevelSetEquationTermBase< InputImageType, LevelSetContainerType >;
81   using TermPointer = typename TermType::Pointer;
82 
83   /** Set/Get the input image to be segmented. */
84   itkSetObjectMacro( Input, InputImageType );
85   itkGetModifiableObjectMacro(Input, InputImageType );
86 
87   itkSetMacro( CurrentLevelSetId, LevelSetIdentifierType );
88   itkGetMacro( CurrentLevelSetId, LevelSetIdentifierType );
89 
90   itkSetObjectMacro( LevelSetContainer, LevelSetContainerType );
91   itkGetModifiableObjectMacro(LevelSetContainer, LevelSetContainerType );
92 
93   /** Add a term to the end of the container  */
94   void PushTerm( TermType* iTerm );
95 
96   /** Replace the pointer to the term with the given id */
97   void AddTerm( const TermIdType& iId, TermType* iTerm );
98 
99   /** Get the term with the given id */
100   TermType* GetTerm( const TermIdType& iId );
101 
102   /** Get the term with the given name */
103   TermType* GetTerm( const std::string& iName );
104 
105   /** \todo  */
106   void Initialize( const LevelSetInputIndexType& iP );
107 
108   /** Supply the update at a given pixel location to update the term parameters */
109   void UpdatePixel( const LevelSetInputIndexType& iP,
110                     const LevelSetOutputRealType & oldValue,
111                     const LevelSetOutputRealType & newValue );
112 
113   /** Initialize the term parameters prior to the start of an iteration */
114   void InitializeParameters();
115 
116   /** Evaluate the term at a given pixel location */
117   LevelSetOutputRealType Evaluate( const LevelSetInputIndexType& iP );
118 
119   LevelSetOutputRealType Evaluate( const LevelSetInputIndexType& iP,
120                                    const LevelSetDataType& iData );
121 
122   /** Update the term parameters at end of iteration */
123   void Update();
124 
125   /** Return the CFL contribution of the current term */
126   LevelSetOutputRealType ComputeCFLContribution() const;
127 
128   void ComputeRequiredData( const LevelSetInputIndexType& iP,
129                             LevelSetDataType& ioData );
130 
131 protected:
132 
133   using MapTermContainerType = std::map< TermIdType, TermPointer >;
134   using MapTermContainerIteratorType = typename MapTermContainerType::iterator;
135   using MapTermContainerConstIteratorType = typename MapTermContainerType::const_iterator;
136 
137 public:
138   class Iterator;
139   friend class Iterator;
140 
141   class ConstIterator
142   {
143   public:
144     ConstIterator() = default;
ConstIterator(const MapTermContainerConstIteratorType & it)145     ConstIterator( const MapTermContainerConstIteratorType& it ) : m_Iterator( it ) {}
146     ~ConstIterator() = default;
ConstIterator(const Iterator & it)147     ConstIterator( const Iterator& it ) : m_Iterator( it.m_Iterator ) {}
148     ConstIterator & operator * () { return *this; }
149     ConstIterator * operator->() { return this; }
150     ConstIterator & operator++()
151       {
152       ++m_Iterator;
153       return *this;
154       }
155     ConstIterator operator++(int)
156       {
157       ConstIterator tmp( *this );
158       ++(*this);
159       return tmp;
160       }
161     ConstIterator & operator--()
162       {
163       --m_Iterator;
164       return *this;
165       }
166     ConstIterator operator--(int)
167       {
168       ConstIterator tmp( *this );
169       --(*this);
170       return tmp;
171       }
172     bool operator == (const Iterator& it) const
173       {
174       return (m_Iterator == it.m_Iterator);
175       }
176     bool operator != (const Iterator& it) const
177       {
178       return (m_Iterator != it.m_Iterator);
179       }
180     bool operator == (const ConstIterator& it) const
181       {
182       return (m_Iterator == it.m_Iterator);
183       }
184     bool operator != (const ConstIterator& it) const
185       {
186       return (m_Iterator != it.m_Iterator);
187       }
GetIdentifier()188     TermIdType GetIdentifier() const
189       {
190       return m_Iterator->first;
191       }
192 
GetTerm()193     TermType * GetTerm() const
194       {
195       return m_Iterator->second;
196       }
197   private:
198     MapTermContainerConstIteratorType m_Iterator;
199     friend class Iterator;
200   };
201 
202   class Iterator
203   {
204   public:
205     Iterator() = default;
Iterator(const MapTermContainerIteratorType & it)206     Iterator( const MapTermContainerIteratorType& it ) : m_Iterator( it ) {}
Iterator(const ConstIterator & it)207     Iterator( const ConstIterator& it ) : m_Iterator( it.m_Iterator ) {}
208     ~Iterator() = default;
209 
210     Iterator & operator * () { return *this; }
211     Iterator * operator ->() { return this; }
212 
213     Iterator & operator++()
214       {
215       ++m_Iterator;
216       return *this;
217       }
218     Iterator operator++(int)
219       {
220        Iterator tmp( *this );
221       ++(*this);
222       return tmp;
223       }
224     Iterator & operator--()
225       {
226       --m_Iterator;
227       return *this;
228       }
229     Iterator operator--(int)
230       {
231       Iterator tmp( *this );
232       --(*this);
233       return tmp;
234       }
235 
236     bool operator==(const Iterator& it) const
237       {
238       return (m_Iterator==it.m_Iterator);
239       }
240     bool operator!=(const Iterator& it) const
241       {
242       return (m_Iterator!=it.m_Iterator);
243       }
244     bool operator==(const ConstIterator& it)const
245       {
246       return (m_Iterator == it.m_Iterator);
247       }
248     bool operator!=(const ConstIterator& it)const
249       {
250       return (m_Iterator != it.m_Iterator);
251       }
GetIdentifier()252     TermIdType GetIdentifier() const
253       {
254       return m_Iterator->first;
255       }
256 
GetTerm()257     TermType * GetTerm() const
258       {
259       return m_Iterator->second;
260       }
261   private:
262     MapTermContainerIteratorType m_Iterator;
263     friend class ConstIterator;
264   };
265 
266    Iterator Begin();
267    Iterator End();
268 
269   ConstIterator Begin() const;
270   ConstIterator End() const;
271 
272 protected:
273   LevelSetEquationTermContainer();
274 
275   ~LevelSetEquationTermContainer() override = default;
276 
277   LevelSetIdentifierType    m_CurrentLevelSetId;
278   LevelSetContainerPointer  m_LevelSetContainer;
279 
280   InputImagePointer         m_Input;
281 
282   using HashMapStringTermContainerType = std::unordered_map< std::string, TermPointer >;
283 
284   HashMapStringTermContainerType m_NameContainer;
285 
286   using RequiredDataType = typename TermType::RequiredDataType;
287   RequiredDataType  m_RequiredData;
288 
289   MapTermContainerType  m_Container;
290 
291   using MapCFLContainerType = std::map< TermIdType, LevelSetOutputRealType >;
292   using MapCFLContainerIterator = typename MapCFLContainerType::iterator;
293   using MapCFLContainerConstIterator = typename MapCFLContainerType::const_iterator;
294 
295   MapCFLContainerType   m_TermContribution;
296 };
297 
298 }
299 #ifndef ITK_MANUAL_INSTANTIATION
300 #include "itkLevelSetEquationTermContainer.hxx"
301 #endif
302 
303 #endif // itkLevelSetEquationTermContainer_h
304