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