KWStyle - itkDataObject.h
 
Matrix View
Description

1 /*=========================================================================
2
3   Program:   Insight Segmentation & Registration Toolkit
4   Module:    $RCSfile: itkDataObject.h.html,v $
5   Language:  C++
6   Date:      $Date: 2006/01/17 19:15:34 $
7   Version:   $Revision: 1.4 $
8
9   Copyright (c) Insight Software Consortium. All rights reserved.
10   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11
12   Portions of this code are covered under the VTK copyright.
13   See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.
14
15      This software is distributed WITHOUT ANY WARRANTY; without even 
16      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
17 IND *****PURPOSE.  See the above copyright notices for more information.
18
19 =========================================================================*/
20 #ifndef __itkDataObject_h
21 #define __itkDataObject_h
22
23 #include "itkObject.h"
24 #include "itkSmartPointerForwardReference.h"
25 #include "itkWeakPointer.h"
26 #include "itkExceptionObject.h"
27
28 namespace itk
29 {
30
31 class ProcessObject;
32 class DataObject;
33   
34 /*--------------------Data Object Exceptions---------------------------*/
35
36 /** \brief Exception object for DataObject exceptions */
37 MCM class ITKCommon_EXPORT DataObjectError : public ExceptionObject
38 {
39 public:
40   /** Default constructor.  Needed to ensure the exception object can be
41    * copied. */
42   DataObjectError();
43   
44   /** Destructor. Need to specify empty throw() to avoid warnings. */
45   virtual ~DataObjectError() throw() {}
46   
47   /** Constructor. Needed to ensure the exception object can be copied. */
48   DataObjectError(const char *file, unsigned int lineNumber);
49
50   /** Constructor. Needed to ensure the exception object can be copied. */
51   DataObjectError(const std::string& file, unsigned int lineNumber);
52
53   /** Copy constructor. Needed to ensure the exception object can be copied. */
54   DataObjectError(const DataObjectError &orig);
55
56   /** Operator=.  Needed to ensure the exception object can be copied. */
57   DataObjectError& operator=( const DataObjectError& orig);
58
59   /** Standard type macro */
60   itkTypeMacro(DataObjectError, ExceptionObject);
61
62   /** Set the data object that is throwing this exception. */
63   void SetDataObject(DataObject *dobj);
64
65   /** Get the data object that is throwing this exception. */
66   DataObject* GetDataObject();
67
68 protected:
69   /** Print exception information.  This method can be overridden by
70    * specific exception subtypes.  The default is to print out the
71    * location where the exception was first thrown and any description
72    * provided by the ``thrower''.   */
73   virtual void PrintSelf(std::ostream& os, Indent indent) const;
74     
75 private:
76   DataObject *m_DataObject;
77 };
78
79   
80 /**
81  * Exception object for invalid requested region
82  */
83 MCM class ITKCommon_EXPORT InvalidRequestedRegionError : public DataObjectError
84 {
85 IND *public:
86 LEN   /** Default constructor. Needed to ensure the exception object can be copied. */
87   InvalidRequestedRegionError();
88   
89   /** Destructor. Need to specify empty throw() to avoid warnings. */
90   virtual ~InvalidRequestedRegionError() throw() {}
91
92   /** Constructor. Needed to ensure the exception object can be copied. */
93   InvalidRequestedRegionError(const char *file, unsigned int lineNumber);
94
95   /** Constructor. Needed to ensure the exception object can be copied. */
96   InvalidRequestedRegionError(const std::string& file, unsigned int lineNumber);
97
98   /** Copy constructor.  Needed to ensure the exception object can be copied. */
99   InvalidRequestedRegionError(const InvalidRequestedRegionError &orig);
100
101   /** Operator=.  Needed to ensure the exception object can be copied. */
102 LEN   InvalidRequestedRegionError& operator=( const InvalidRequestedRegionError& orig);
103
104   /** Standard type macro */
105   itkTypeMacro(InvalidRequestedRegionError, DataObjectError);
106
107 protected:
108   /** Print exception information.  This method can be overridden by
109    * specific exception subtypes.  The default is to print out the
110    * location where the exception was first thrown and any description
111    * provided by the ``thrower''.   */
112   virtual void PrintSelf(std::ostream& os, Indent indent) const;
113   
114 };
115
116
117 /*----------------------------Data Object--------------------------------*/  
118
119 /** \class DataObject
120  * \brief Base class for all data objects in ITK.
121  *
122  * This is the base class for all data objects in the Insight data
123  * processing pipeline. A data object is an object that represents and
124  * provides access to data. ProcessObjects (i.e., filters) operate on
125  * input data objects, producing new data objects as output.
126  * ProcessObject and DataObject are connected together into data flow
127  * pipelines.
128  *
129  * The data flow pipeline architecture requires that DataObjects and
130  * ProcessObjects negotiate the flow of information.  When the tail of
131  * a pipeline is instructed to Update(), a series of requests are
132  * propagated up the pipeline (from a ProcessObject to its inputs
133  * (DataObjects), from these inputs to their sources (ProcessObjects),
134  * etc.). A call to Update() entails 3 passes up the pipeline (though
135  * not all passes will traverse the entire pipeline).  The first pass
136  * up the pipeline determines when various components of the pipeline
137  * were last modified and hence which components will need to be
138  * updated.  As this first pass in unwinding, meta information about
139  * the DataObjects (for instance image spacing and data size) are
140  * passed down the pipeline.  The second pass up the pipeline
141  * propagates a request for a specific piece of information (for
142  * instance a sub-region of an image). A request for a piece of a
143  * DataObject is propagated to its source, from there to its inputs,
144  * etc. allowing each ProcessObject to determine whether (1) it can
145  * already satisfy the request (the requested block of data is already
146  * available) or (2) the ProcessObject will need to request a new
147  * block of data on input to satisfy the output request.  Finally, a
148  * pass is made up the pipeline to actually calculate the values for
149  * the various blocks of data requested (i.e. pixel values are finally
150  * calculated).  This final pass will only traverse up the pipeline as
151  * far as the first two passes have identified.  For instance, to
152  * satisfy a given request at the tail of a pipeline, only the lower
153  * few ProcessObjects may have to re-execute.
154  *
155  * There are three types of information negotiated by the pipeline
156  * (prior to actual calculation of the bulk data): modified times,
157  * meta data, and regions.  The modified times keep track of when
158  * various data objects were last modified and/updated and the when
159  * the various process objects were modified.  The meta data is any
160  * extra information about the data object that is not part of the
161  * bulk data.  For instance, an Image maintains pixel spacing and
162  * origin meta data.  Finally, the pipeline negotiation process passes
163  * requests up the pipeline in the form of Regions.  A DataObject can
164  * have as many as three regions (which themselves could be considered
165  * meta data): LargestPossibleRegion, RequestedRegion, and
166  * BufferedRegion.  The LargestPossibleRegion is the entirety of the
167  * dataset (for instance how big is the dataset on disk).
168  * LargestPossibleRegions are negotiated during the first pass of a
169  * pipeline update (via the method
170  * ProcessObject::GenerateOutputInformation() which is called from
171  * ProcessObject::UpdateOutputInformation().  The RequestedRegion is
172  * the amount of the DataObject that is requested by the user or
173  * pipeline. RequestedRegions are negotiated during the second pass of
174  * a pipeline update (via the methods
175  * ProcessObject::EnlargeOutputRequestedRegion(),
176  * ProcessObject::GenerateOutputRequestedRegion(),
177  * ProcessObject::GenerateInputRequestedRegion() which are called from
178  * ProcessObject::PropagateRequestedRegion()). The BufferedRegion is
179  * the amount of the DataObject that is currently in memory.
180  * BufferedRegions are defined during the final pass of a pipeline
181  * update (when ProcessObjects finally calculate the bulk data via the
182  * methods ProcessObject::GenerateData() or
183  * ProcessObject::ThreadedGenerateData() which are called by
184  * ProcessObject::UpdateOutputData()). These three regions can be
185  * different but must satisfy the relationship RequestedRegion <=
186  * BufferedRegion <= LargestPossibleRegion. For instance, an Image
187  * could be 512x512x200 on disk (LargestPossibleRegion) but the
188  * application may only have a 256x256x50 section of the dataset in
189  * memory (BufferedRegion) and the user wants to operate on a
190  * 100x100x1 section of the buffer (RequestedRegion).
191  *
192  * Region negotiation is not applicable for all types of DataObjects.
193  * For instance, an EquivalencyTable of segmentation labels can be
194  * passed from ProcessObject to ProcessObject as any other DataObject
195  * but an EquivalencyTable does not support the concept of a
196  * sub-region. Therefore, the region negotiations at the DataObject
197  * (superclass) level are implemented as "abstract" concepts (not to
198  * be confused with a C++ abstract methods), allowing subclasses to
199  * provide specialized implementations on an as needed basis. There
200  * are five methods provided in DataObject that a subclass of
201  * DataObject may have to override for that particular type of
202  * DataObject to flow through the pipeline. These methods should only
203  * have to be specialized for DataObjects that do support
204  * regions. These methods are:
205  *
206  * void UpdateOutputInformation(): This method implements the first
207  * pass of the pipeline update mechanism outlined above.  It is
208  * responsible for identifying when upstream components of the
209  * pipeline have been change (ModifiedTimes and Pipeline
210  * ModifiedTimes) and is responsible for propagating meta data through
211  * the pipeline. In the simplest case, this method simply calls the
212  * DataObject's source's UpdateOutputInformation() method (this is the
213  * default implementation). For DataObjects that support streaming,
214  * this method also propagates LargestPossibleRegions to downstream
215  * ProcessObjects. 
216  *
217  * bool VerifyRequestedRegion(): Verify that the RequestedRegion is
218  * within the LargestPossibleRegion.  For DataObjects that do not
219  * support Regions, this method always returns true.
220  *
221  * bool RequestedRegionIsOutsideOfTheBufferedRegion(): Determine
222  * whether the RequestedRegion is outside of the current
223  * BufferedRegion. This method is used by the second pass of a
224  * pipeline update outlined above.  It is used to determine whether a
225  * filter needs to re-execute in order to satisfy a given request. For
226  * DataObjects that do not support Regions, this method always returns
227  * false. By always returning false, these types of DataObjects will
228  * update solely on the basis of modified times (wherease Images
229  * update based on either modified times or the RequestedRegion
230  * needs). If this method always returned true, the DataObject would
231  * be updated on every single call to Update() (not recommended).
232  *
233  * void SetRequestedRegion(DataObject *): Sets the RequestedRegion of
234  * this DataObject to match the RequestedRegion of the DataObject that
235  * is passed in as a parameter. This method is used by
236  * ProcessObject::GenerateOutputRequestedRegion() and by
237  * ProcessObject::SetNthOutput().  In the former case, it used as an
238  * abstract API so that a ProcessObject can copy a requested region
239  * from one output to all its outputs without knowing the particular
240  * subclass of DataObject.  In the latter case, it used when a
241  * ProcessObject has to create an output object to replace one of its
242  * outputs (and needs to copy the former object's RequestedRegion). In
243  * either case, it allows ProcessObject to perform these actions
244  * without knowing the specifics about the particular subclass of
245  * DataObject. For DataObjects that do not support Regions, this
246  * method does nothing.
247  *
248  * void SetRequestedRegionToLargestPossibleRegion(): Sets the
249  * RequestedRegion of this DataObject to match its
250  * LargestPossibleRegion.  This method is used to force a filter to
251  * produce all of its output on the next call to Update(). For
252  * DataObjects that do not support Regions, this method does nothing.
253  *
254  * 
255  * \sa ProcessObject
256  * \sa ImageBase
257  * \sa Mesh
258  * \ingroup DataRepresentation
259  * \ingroup ITKSystemObjects
260  */
261 class ITKCommon_EXPORT DataObject : public Object
262 {
263 public:
264   /** Standard class typedefs. */
265   typedef DataObject          Self;
266 TDA   typedef Object  Superclass;
267   typedef SmartPointer<Self>  Pointer;
268 TDA   typedef SmartPointer<const Self>  ConstPointer;
269   
270   /** Run-time type information (and related methods). */
271   itkTypeMacro(DataObject,Object);
272
273   /** Separate this data object from the pipeline.  This routine disconnects
274    * a data object from the upstream pipeline. Hence an Update() from
275    * downstream will not propagate back past this data object.  To completely
276    * isolate this data object from the pipeline, the application must remove
277    * this data object from any filters which it is connected as the input. */
278   void DisconnectPipeline();
279   
280   /** Get the process object that generated this data object.
281    * If there is no process object, then the data object has
282    * been disconnected from the pipeline, or the data object
283    * was created manually. (Note: we cannot use the GetObjectMacro()
284    * defined in itkMacro because the mutual dependency of
285    * DataObject and ProcessObject causes compile problems. Also,
286    * a forward reference smart pointer is returned, not a smart pointer, 
287    * because of the circular dependency between the process and data object.)
288    *
289    * GetSource() returns a SmartPointerForwardReference and not a WeakPointer
290    * because it is assumed the code calling GetSource() wants to hold a
291    * long term reference to the source. */
292   SmartPointerForwardReference<ProcessObject> GetSource() const;
293
294   /** Which of the source's outputs corresponds to this data object? */
295   unsigned int GetSourceOutputIndex() const;
296     
297   /** Restore the data object to its initial state. This means releasing
298    * memory. */
299   virtual void Initialize();
300
301   /** Turn on/off a flag to control whether this object's data is released
302    * after being used by a filter.  */
303   void SetReleaseDataFlag(bool flag)
304     {
305 IND ******m_ReleaseDataFlag = flag;
306     }
307   itkGetConstReferenceMacro(ReleaseDataFlag,bool);
308   itkBooleanMacro(ReleaseDataFlag);
309   
310   /** Turn on/off a flag to control whether every object releases its data
311    * after being used by a filter. Being a global flag, it controls the
312    * behavior of all DataObjects and ProcessObjects. */
313   static void SetGlobalReleaseDataFlag(const bool val);
314   static bool GetGlobalReleaseDataFlag();
315   void GlobalReleaseDataFlagOn() 
316     {this->SetGlobalReleaseDataFlag(true);}
317   void GlobalReleaseDataFlagOff() 
318     {this->SetGlobalReleaseDataFlag(false);}
319   
320   /** Release data back to system to conserve memory resource. Used during
321    * pipeline execution.  Releasing this data does not make
322    * down-stream data invalid, so it does not modify the MTime of this data
323    * object.   */
324   void ReleaseData();
325
326   /** Return flag indicating whether data should be released after use  
327    * by a filter.  */
328   bool ShouldIReleaseData() const;
329
330   /** Get the flag indicating the data has been released.  */
331   bool GetDataReleased() const 
332     {return m_DataReleased;}
333   
334   /** Provides opportunity for the data object to insure internal
335    * consistency before access. Also causes owning source/filter (if
336    * any) to update itself. The Update() method is composed of
337    * UpdateOutputInformation(), PropagateRequestedRegion(), and
338    * UpdateOutputData(). This method may call methods that throw an
339    * InvalidRequestedRegionError exception. This exception will leave
340    * the pipeline in an inconsistent state.  You will need to call
341    * ResetPipeline() on the last ProcessObject in your pipeline in
342    * order to restore the pipeline to a state where you can call
343    * Update() again. */
344   virtual void Update();
345
346   /** Update the information for this DataObject so that it can be used
347    * as an output of a ProcessObject.  This method is used in the pipeline
348    * mechanism to propagate information and initialize the meta data
349    * associated with a DataObject.  Any implementation of this method in
350    * a derived class is assumed to call its source's
351    * ProcessObject::UpdateOutputInformation() which determines modified
352    * times, LargestPossibleRegions, and any extra meta data like spacing,
353    * origin, etc. Default implementation simply call's it's source's
354    * UpdateOutputInformation(). */
355   virtual void UpdateOutputInformation();
356
357   /** Methods to update the pipeline. Called internally by the
358    * pipeline mechanism. */
359   virtual void PropagateRequestedRegion() throw (InvalidRequestedRegionError);
360   virtual void UpdateOutputData();
361   
362   /** Reset the pipeline. If an exception is thrown during an Update(),
363    * the pipeline may be in an inconsistent state.  This method clears
364    * the internal state of the pipeline so Update() can be called. */
365   virtual void ResetPipeline();
366
367   /** The maximum MTime of all upstream filters and data objects.
368    * This does not include the MTime of this data object. */
369   void SetPipelineMTime(unsigned long time) 
370     {m_PipelineMTime = time;}
371   itkGetConstReferenceMacro(PipelineMTime,unsigned long);
372
373   /** MTime for the last time this DataObject was generated. */
374   virtual unsigned long GetUpdateMTime() const;
375   
376   /** Setup a DataObject to receive new data.  This method is called
377    * by the pipeline mechanism on each output of filter that needs
378    * to execute.  The default implementation is to return a DataObject
379    * to its initial state.  This may involve releasing previously
380    * allocated bulk data.  Subclasses of DataObject may want to
381    * override this method and/or the Initialize() method if they
382    * want a different default behavior (for instance a DataObject
383    * might want finer control over its bulk data memory management). */
384   virtual void PrepareForNewData() 
385     {this->Initialize();}
386
387   /** Inform the pipeline mechanism that data has been generated.  This
388    * method is called by ProcessObject::UpdateOutputData() once the
389    * process object has finished generating its data. This essentially
390    * marks the DataObject as being updated and ready for use. */
391   void DataHasBeenGenerated();
392
393   
394   /** Set the RequestedRegion to the LargestPossibleRegion.  This
395    * forces a filter to produce all of the output in one execution
396    * (i.e. not streaming) on the next call to Update(). */
397   virtual void SetRequestedRegionToLargestPossibleRegion() {};
398
399   /** Determine whether the RequestedRegion is outside of the
400    * BufferedRegion. This method returns true if the RequestedRegion
401    * is outside the BufferedRegion (true if at least one pixel is
402    * outside). This is used by the pipeline mechanism to determine
403    * whether a filter needs to re-execute in order to satisfy the
404    * current request.  If the current RequestedRegion is already
405    * inside the BufferedRegion from the previous execution (and the
406    * current filter is up to date), then a given filter does not need
407    * to re-execute */
408   virtual bool RequestedRegionIsOutsideOfTheBufferedRegion()
409     { return false; }
410
411   /** Verify that the RequestedRegion is within the LargestPossibleRegion.  
412    *
413    * If the RequestedRegion is not within the LargestPossibleRegion,
414    * then the filter cannot possibly satisfy the request. This method
415    * returns true if the request can be satisfied (even if it will be
416    * necessary to process the entire LargestPossibleRegion) and
417    * returns false otherwise.  This method is used by
418    * PropagateRequestedRegion().  PropagateRequestedRegion() throws a
419    * InvalidRequestedRegionError exception if the requested region is
420    * not within the LargestPossibleRegion. Default implementation
421    * simply returns true in order to support DataObjects that do not
422    * need regions (for instance itk::EquivalencyTable). */
423   virtual bool VerifyRequestedRegion() { return true; };
424
425   /** Copy information from the specified data set.  This method is
426    * part of the pipeline execution model. By default, a ProcessObject
427    * will copy meta-data from the first input to all of its
428    * outputs. See ProcessObject::GenerateOutputInformation().  Each
429    * subclass of DataObject is responsible for being able to copy
430 WCM    * whatever meta-data it needs from from another DataObject.
431    * The default implementation of this method is empty. If a subclass
432    * overrides this method, it should always call its superclass'
433    * version. */
434   virtual void CopyInformation(const DataObject*) {};
435   
436   /** Set the requested region from this data object to match the requested
437    * region of the data object passed in as a parameter.  For
438    * DataObject's that do not support Regions, this method does
439    * nothing. Subclasses of DataObject that do support Regions,
440    * provide an alternative implementation. */
441   virtual void SetRequestedRegion(DataObject *) {};
442   
443   /** Method for grafting the content of one data object into another one.
444    * This method is intended to be overloaded by derived classes. Each one of
445    * them should use dynamic_casting in order to verify that the grafted 
446    * object is actually of the same type as the class on which the Graft()
447    * method was invoked. */
448   virtual void Graft( const DataObject *) {};
449   
450 protected:
451   DataObject();
452   ~DataObject();
453   void PrintSelf(std::ostream& os, Indent indent) const;
454
455   /** Propagate a call to ResetPipeline(). Called only from ProcessObject. */
456   virtual void PropagateResetPipeline();
457   
458 private:
459   DataObject(const Self&); //purposely not implemented
460   void operator=(const Self&); //purposely not implemented
461
462   /** Who generated this data? */
463   mutable WeakPointer<ProcessObject> m_Source; 
464   mutable unsigned int m_SourceOutputIndex;
465     
466   /** When was this data last generated? */
467   TimeStamp m_UpdateMTime;  
468
469   bool m_ReleaseDataFlag; //Data will release after use by a filter if on
470   bool m_DataReleased; //Keep track of data release during pipeline execution
471
472   /** The maximum MTime of all upstream filters and data objects.
473    * This does not include the MTime of this data object. */
474   unsigned long m_PipelineMTime;
475
476   /** Static member that controls global data release after use by filter. */
477   static bool m_GlobalReleaseDataFlag;
478
479   /** Connect the specified process object to the data object. This
480    * should only be called from a process object. The second parameter
481    * indicates which of the source's outputs corresponds to this data
482    * object. */
483   bool ConnectSource(ProcessObject *s, unsigned int idx) const;
484
485   /** Disconnect the specified process object from the data
486    * object. This should only be called from a process object. An
487    * application should call DataObject::DisconnectPipeline() if it
488    * wants to disconnect a data object from a pipeline. The second
489    * parameter indicates which of the source's outputs corresponds to
490    * this data object. If the specified source output index does not
491    * match the index cached when the data object was connected to the
492    * pipeline (see ConnectSource), then nothing is done. */
493   bool DisconnectSource(ProcessObject *s, unsigned int idx) const;
494   
495   /** Friends of DataObject */
496   friend class ProcessObject;
497   friend class DataObjectError;
498 IND **};
499
500 // end namespace itk
501   
502 #endif
503

Generated by KWStyle 1.0b on Tuesday January,17 at 02:14:05PM
© Kitware Inc.