KWStyle - itkProcessObject.cxx
 
Matrix View
Description

1 /*=========================================================================
2
3   Program:   Insight Segmentation & Registration Toolkit
4   Module:    $RCSfile: itkProcessObject.cxx.html,v $
5   Language:  C++
6   Date:      $Date: 2006/01/17 19:15:45 $
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 DEF =========================================================================*/
20 #include "itkProcessObject.h"
21 #include "itkDataObject.h"
22 #include "itkObjectFactory.h"
23 #include "itkCommand.h"
24 #include <functional>
25 #include <algorithm>
26
27 namespace itk
28 {
29
30 /**
31  * Instantiate object with no start, end, or progress methods.
32  */
33 ProcessObject
34 ::ProcessObject()
35 {
36   m_NumberOfRequiredInputs = 0;
37
38   m_NumberOfRequiredOutputs = 0;
39
40   m_AbortGenerateData = false;
41   m_Progress = 0.0;
42   m_Updating = false;
43   
44   m_Threader = MultiThreader::New();
45   m_NumberOfThreads = m_Threader->GetNumberOfThreads();
46
47   m_ReleaseDataBeforeUpdateFlag = true;
48 }
49
50 /**
51  * This is a default implementation to make sure we have something.
52  * Once all the subclasses of ProcessObject provide an appopriate
53  * MakeOutput(), then ProcessObject::MakeOutput() can be made pure
54  * virtual.
55  */
56 DataObject::Pointer
57 ProcessObject
58 ::MakeOutput(unsigned int)
59 {
60   return static_cast<DataObject*>(DataObject::New().GetPointer());
61 }
62   
63 /**
64  * Destructor for the ProcessObject class. We've got to
65  * UnRegister() the use of any input classes.
66  */
67 ProcessObject
68 ::~ProcessObject()
69 {
70   // Tell each output that we are going away.  If other objects have a 
71   // reference to one of these outputs, the data object will not be deleted
72   // when the process object is deleted.  However, the data object's source
73   // will still point back to the now nonexistent process object if we do not
74   // clean things up now.
75   unsigned int idx;
76   for (idx = 0; idx < m_Outputs.size(); ++idx)
77     {
78     if (m_Outputs[idx])
79       {
80       // let the output know we no longer want to associate with the object
81       m_Outputs[idx]->DisconnectSource(this, idx);
82       // let go of our reference to the data object
83       m_Outputs[idx] = 0;
84       }
85     }
86 }
87
88 //typedef DataObject *DataObjectPointer;
89
90 /**
91  * Called by constructor to set up input array.
92  */
93 void 
94 ProcessObject
95 ::SetNumberOfInputs(unsigned int num)
96 {
97   // in case nothing has changed.
98   if (num == m_Inputs.size())
99     {
100     return;
101     }
102   m_Inputs.resize(num);
103   this->Modified();
104 }
105
106 /**
107  * Get the number of specified inputs
108  */
109 std::vector<SmartPointer<DataObject> >::size_type
110 ProcessObject
111 ::GetNumberOfValidRequiredInputs() const
112 {
113   std::vector<DataObjectPointer>::size_type num;
114   if (m_NumberOfRequiredInputs < m_Inputs.size())
115     {
116     num = m_NumberOfRequiredInputs;
117     }
118   else
119     {
120     num = m_Inputs.size();
121     }
122   // count the number of non-null inputs
123   // this used to use std::count_if, but that function object
124   // did not work correctly with SunPro CC 5.6.
125   int count = 0;
126   for(std::vector<DataObjectPointer>::const_iterator i = m_Inputs.begin();
127 IND ******i < (m_Inputs.begin() + num); ++i)
128     {
129     if((*i).IsNotNull())
130       {
131       count++;
132       }
133     }
134   return count;
135 }
136  
137 /**
138  * Adds an input to the first null position in the input list.
139  * Expands the list memory if necessary
140  */
141 void 
142 ProcessObject
143 ::AddInput(DataObject *input)
144 {
145   std::vector<DataObjectPointer>::size_type idx;
146   
147   this->Modified();
148   
149   for (idx = 0; idx < m_Inputs.size(); ++idx)
150     {
151     if (!m_Inputs[idx])
152       {
153       m_Inputs[idx] = input;
154       return;
155       }
156     }
157   
158   this->SetNumberOfInputs( static_cast<int>( m_Inputs.size() + 1 ) );
159   m_Inputs[ static_cast<int>( m_Inputs.size() ) - 1] = input;
160 }
161
162
163 /**
164  * Remove an input.
165  *
166  * Removes the first occurence of the given OutputObject from the
167  * inputs to this ProcessObject.  If it's the last object on the
168  * list, shortens the list.
169  */
170 void 
171 ProcessObject
172 ::RemoveInput(DataObject *input)
173 {
174   if (!input)
175     {
176     return;
177     }
178   
179   // find the input in the list of inputs
180   DataObjectPointerArray::iterator pos = 
181 IND ****std::find(m_Inputs.begin(), m_Inputs.end(), input);
182
183   if(pos == m_Inputs.end())
184     {
185     itkDebugMacro("tried to remove an input that was not in the list");
186     return;
187     }
188
189   // Set the position in the m_Inputs containing input to 0
190   *pos = 0;
191
192   // if that was the last input, then shrink the list
193   if (pos == m_Inputs.end() - 1 )
194     {
195     this->SetNumberOfInputs( static_cast<int>( m_Inputs.size() ) - 1);
196     }
197
198   this->Modified();
199 }
200
201
202 /**
203  * Set an Input of this filter. This method 
204  * does Register()/UnRegister() manually to
205  * deal with the fact that smart pointers aren't
206  * around to do the reference counting.
207  */
208 void 
209 ProcessObject
210 ::SetNthInput(unsigned int idx, DataObject *input)
211 {
212   // does this change anything?
213   if ( idx < m_Inputs.size() && m_Inputs[idx] == input )
214     {
215     return;
216     }
217   
218   // Expand array if necessary.
219   if (idx >= m_Inputs.size())
220     {
221     this->SetNumberOfInputs(idx + 1);
222     }
223   
224   m_Inputs[idx] = input;
225
226   this->Modified();
227 }
228
229 void 
230 ProcessObject
231 ::RemoveOutput(DataObject *output)
232 {
233   if (!output)
234     {
235     return;
236     }
237   
238   // find the input in the list of inputs
239   DataObjectPointerArray::iterator pos = 
240 IND ****std::find(m_Outputs.begin(), m_Outputs.end(), output);
241
242   if(pos == m_Outputs.end())
243     {
244     itkDebugMacro("tried to remove an output that was not in the list");
245     return;
246     }
247
248   // let the output know we no longer want to associate with the object
249   (*pos)->DisconnectSource(this, pos - m_Outputs.begin());
250   // let go of our reference to the data object
251   *pos = 0;
252
253   // if that was the last output, then shrink the list
254   if (pos == m_Outputs.end() - 1 )
255     {
256     this->SetNumberOfOutputs( static_cast<int>( m_Outputs.size() ) - 1);
257     }
258
259   this->Modified();
260 }
261
262
263 /**
264  * Set an output of this filter. This method specifically
265  * does not do a Register()/UnRegister() because of the 
266  * desire to break the reference counting loop.
267  */
268 void 
269 ProcessObject
270 ::SetNthOutput(unsigned int idx, DataObject *output)
271 {
272   // does this change anything?
273   if ( idx < m_Outputs.size() && output == m_Outputs[idx])
274     {
275     return;
276     }
277
278   // Expand array if necessary.
279   if (idx >= m_Outputs.size())
280     {
281     this->SetNumberOfOutputs(idx + 1);
282     }
283
284   // Keep a handle to the original output and disconnect the old output from
285   // the pipeline
286   DataObjectPointer oldOutput;
287   if ( m_Outputs[idx] )
288     {
289     oldOutput = m_Outputs[idx];
290     m_Outputs[idx]->DisconnectSource(this, idx);
291     }
292
293   if (output)
294     {
295     output->ConnectSource(this, idx);
296     }
297   // save the current reference (which releases the previous reference)
298   m_Outputs[idx] = output;
299
300   // if we are clearing an output, we need to create a new blank output
301   // so we are prepared for the next Update(). this copies the requested
302   // region ivar
303   if (!m_Outputs[idx])
304     {
305     itkDebugMacro( " creating new output object." );
306     DataObjectPointer newOutput = this->MakeOutput(idx);
307     this->SetNthOutput(idx, newOutput);
308
309     // If we had an output object before, copy the requested region
310 WCM     // ivars and release data flag to the the new output
311     if (oldOutput)
312       {
313       newOutput->SetRequestedRegion( oldOutput );
314       newOutput->SetReleaseDataFlag( oldOutput->GetReleaseDataFlag() );
315       }
316     }
317
318   this->Modified();
319 }
320
321 /**
322  * Adds an output to the first null position in the output list.
323  * Expands the list memory if necessary
324  */
325 void 
326 ProcessObject
327 ::AddOutput(DataObject *output)
328 {
329   unsigned int idx;
330   
331   for (idx = 0; idx < m_Outputs.size(); ++idx)
332     {
333     if ( m_Outputs[idx].IsNull() )
334       {
335       m_Outputs[idx] = output;
336
337       if (output)
338         {
339         output->ConnectSource(this, idx);
340         }
341       this->Modified();
342   
343       return;
344       }
345     }
346   
347   this->SetNumberOfOutputs( static_cast<int>( m_Outputs.size() ) + 1);
348   m_Outputs[ static_cast<int>( m_Outputs.size() ) - 1] = output;
349   if (output)
350     {
351     output->ConnectSource(this, static_cast<int>( m_Outputs.size() ) - 1 );
352     }
353   this->Modified();
354 }
355
356 /**
357  * Called by constructor to set up output array.
358  */
359 void 
360 ProcessObject
361 ::SetNumberOfOutputs(unsigned int num)
362 {
363
364   // in case nothing has changed.
365   if (num == m_Outputs.size())
366     {
367     return;
368     }
369   m_Outputs.resize(num);
370   this->Modified();
371 }
372
373
374 /**
375  *
376  */
377 DataObject *
378 ProcessObject
379 ::GetOutput(unsigned int i)
380 {
381   if (m_Outputs.size() < i+1)
382     {
383     return NULL;
384     }
385   
386   return m_Outputs[i].GetPointer();
387 }
388
389 const DataObject *
390 ProcessObject
391 ::GetOutput(unsigned int i) const
392 {
393   if (m_Outputs.size() < i+1)
394     {
395     return NULL;
396     }
397   
398   return m_Outputs[i].GetPointer();
399 }
400
401
402 /**
403  *
404  */
405 DataObject *
406 ProcessObject
407 ::GetInput(unsigned int i)
408 {
409   if (m_Inputs.size() < i+1)
410     {
411     return NULL;
412     }
413   
414   return m_Inputs[i].GetPointer();
415 }
416
417 const DataObject *
418 ProcessObject
419 ::GetInput(unsigned int i) const
420 {
421   if (m_Inputs.size() < i+1)
422     {
423     return NULL;
424     }
425   
426   return m_Inputs[i].GetPointer();
427 }
428
429
430 /**
431  * Update the progress of the process object. If a ProgressMethod exists, 
432  * execute it. Then set the Progress ivar to amount. The parameter amount 
433  * should range between (0,1).
434  */
435 void 
436 ProcessObject
437 ::UpdateProgress(float amount)
438 {
439   m_Progress = amount;
440   this->InvokeEvent( ProgressEvent() );
441 }
442
443
444 /**
445  *
446  */
447 bool 
448 ProcessObject
449 ::GetReleaseDataFlag() const
450 {
451   if (this->GetOutput(0))
452     {
453     return this->GetOutput(0)->GetReleaseDataFlag();
454     }
455   itkWarningMacro(<<"Output doesn't exist!");
456   return false;
457 }
458
459
460 /**
461  *
462  */
463 void 
464 ProcessObject
465 ::SetReleaseDataFlag(bool val)
466 {
467   unsigned int idx;
468   
469   for (idx = 0; idx < m_Outputs.size(); idx++)
470     {
471     if (m_Outputs[idx])
472       {
473       m_Outputs[idx]->SetReleaseDataFlag(val);
474       }
475     }
476 }
477
478
479 /**
480  *
481  */
482 void 
483 ProcessObject
484 ::PrintSelf(std::ostream& os, Indent indent) const
485 {
486   Superclass::PrintSelf(os,indent);
487
488   os << indent << "Number Of Required Inputs: "
489      << m_NumberOfRequiredInputs << std::endl;
490
491   os << indent << "Number Of Required Outputs: "
492      << m_NumberOfRequiredOutputs << std::endl;
493
494   os << indent << "Number Of Threads: "
495      << m_NumberOfThreads << std::endl;
496
497   os << indent << "ReleaseDataFlag: " 
498      << (this->GetReleaseDataFlag() ? "On" : "Off") << std::endl;
499
500   os << indent << "ReleaseDataBeforeUpdateFlag: "
501      << (m_ReleaseDataBeforeUpdateFlag ? "On" : "Off") << std::endl;
502   
503   if ( m_Inputs.size())
504     {
505     std::vector<DataObjectPointer>::size_type idx;
506     for (idx = 0; idx < m_Inputs.size(); ++idx)
507       {
508       os << indent << "Input " << static_cast<int>( idx );
509       os << ": (" << m_Inputs[idx].GetPointer() << ")\n";
510       }
511     }
512   else
513     {
514     os << indent <<"No Inputs\n";
515     }
516   if ( m_Outputs.size())
517     {
518     std::vector<DataObjectPointer>::size_type idx;
519     for (idx = 0; idx < m_Outputs.size(); ++idx)
520       {
521       os << indent << "Output " << static_cast<int>( idx );
522       os << ": (" << m_Outputs[idx].GetPointer() << ")\n";
523       }
524     }
525   else
526     {
527     os << indent <<"No Output\n";
528     }
529
530 LEN   os << indent << "AbortGenerateData: " << (m_AbortGenerateData ? "On\n" : "Off\n");
531   os << indent << "Progress: " << m_Progress << "\n";
532
533   os << indent << "Multithreader: " << std::endl;
534   m_Threader->PrintSelf(os, indent.GetNextIndent());
535 }
536
537
538 EML
539 /**
540  * The following methods are used to coordinate the execution of the
541  * data processing pipeline.
542  */
543
544
545 /**
546  *
547  */
548 void 
549 ProcessObject
550 ::Update()
551 {
552   if (this->GetOutput(0))
553     {
554     this->GetOutput(0)->Update();
555     }
556 }
557
558 void
559 ProcessObject
560 ::ResetPipeline()
561 {
562   if (this->GetOutput(0))
563     {
564     this->GetOutput(0)->ResetPipeline();
565     }
566 }
567
568 void
569 ProcessObject
570 ::PropagateResetPipeline()
571 {
572   // 
573   // Reset this object.
574   //
575   // Clear the updating flag.
576   m_Updating = 0;
577
578   //
579   // Loop through the inputs
580   //
581   unsigned int idx;
582   DataObject::Pointer input;
583   for (idx = 0; idx < m_Inputs.size(); ++idx)
584     {
585     if (m_Inputs[idx])
586       {
587       input = m_Inputs[idx];
588
589       /**
590        * Propagate the ResetPipeline call
591        */
592       input->PropagateResetPipeline();
593       }
594     }
595 }
596
597
598 /**
599  *
600  */
601 void 
602 ProcessObject
603 ::UpdateOutputInformation()
604 {
605   unsigned long t1, t2;
606   std::vector<DataObjectPointer>::size_type idx;
607   DataObject *input;
608   DataObject *output;
609
610   /**
611    * Watch out for loops in the pipeline
612    */
613   if ( m_Updating )
614     {
615     /**
616      * Since we are in a loop, we will want to update. But if
617      * we don't modify this filter, then we will not execute
618      * because our OutputInformationMTime will be more recent than
619      * the MTime of our output.
620      */
621     this->Modified();
622     return;
623     }
624
625   /**
626    * We now wish to set the PipelineMTime of each output DataObject to
627    * the largest of this ProcessObject's MTime, all input DataObject's
628    * PipelineMTime, and all input's MTime.  We begin with the MTime of
629    * this ProcessObject.
630    */
631   t1 = this->GetMTime();
632
633   /**
634    * Loop through the inputs
635    */
636   for (idx = 0; idx < m_Inputs.size(); ++idx)
637     {
638     if (m_Inputs[idx])
639       {
640       input = m_Inputs[idx];
641
642       /**
643        * Propagate the UpdateOutputInformation call
644        */
645       m_Updating = true;
646       input->UpdateOutputInformation();
647       m_Updating = false;
648       
649       /**
650        * What is the PipelineMTime of this input? Compare this against
651        * our current computation to find the largest one.
652        */
653       t2 = input->GetPipelineMTime();
654
655       if (t2 > t1)
656         {
657         t1 = t2;
658         }
659
660       /**
661        * Pipeline MTime of the input does not include the MTime of the 
662        * data object itself. Factor these mtimes into the next PipelineMTime
663        */
664       t2 = input->GetMTime();
665       if (t2 > t1)
666         {
667         t1 = t2;
668         }
669       }
670     }
671
672   /**
673    * Call GenerateOutputInformation for subclass specific information.
674    * Since UpdateOutputInformation propagates all the way up the pipeline,
675    * we need to be careful here to call GenerateOutputInformation only if
676    * necessary. Otherwise, we may cause this source to be modified which
677    * will cause it to execute again on the next update.
678    */
679   if (t1 > m_OutputInformationMTime.GetMTime())
680     {
681     for (idx = 0; idx < m_Outputs.size(); ++idx)
682       {
683       output = this->GetOutput( static_cast<int>( idx ) );
684       if (output)
685         {
686         output->SetPipelineMTime(t1);
687         }  
688       }
689     
690     this->GenerateOutputInformation();
691
692     /**
693      * Keep track of the last time GenerateOutputInformation() was called
694      */
695     m_OutputInformationMTime.Modified();
696     }
697 }
698
699
700 /**
701  *
702  */
703 void 
704 ProcessObject
705 ::PropagateRequestedRegion(DataObject *output)
706 {
707   /**
708    * check flag to avoid executing forever if there is a loop
709    */
710   if (m_Updating)
711     {
712     return;
713     }
714
715   /**
716    * Give the subclass a chance to indicate that it will provide
717    * more data then required for the output. This can happen, for
718    * example, when a source can only produce the whole output.
719    * Although this is being called for a specific output, the source
720    * may need to enlarge all outputs.
721    */
722   this->EnlargeOutputRequestedRegion( output );
723
724   /**
725    * Give the subclass a chance to define how to set the requested
726    * regions for each of its outputs, given this output's requested
727    * region.  The default implementation is to make all the output
728    * requested regions the same.  A subclass may need to override this
729    * method if each output is a different resolution.
730    */
731   this->GenerateOutputRequestedRegion( output );
732   
733   /**
734    * Give the subclass a chance to request a larger requested region on 
735    * the inputs. This is necessary when, for example, a filter
736    * requires more data at the "internal" boundaries to 
737    * produce the boundary values - such as an image filter that
738    * derives a new pixel value by applying some operation to a 
739    * neighborhood of surrounding original values. 
740    */
741   this->GenerateInputRequestedRegion();
742
743   /**
744    * Now that we know the input requested region, propagate this
745    * through all the inputs.
746    */
747   m_Updating = true;
748   std::vector<DataObjectPointer>::size_type idx;
749   for (idx = 0; idx < m_Inputs.size(); ++idx)
750     {
751     if (m_Inputs[idx])
752       {
753       m_Inputs[idx]->PropagateRequestedRegion();
754       }
755     }
756   m_Updating = false;
757 }
758
759
760 /**
761  * By default we require all the input to produce the output. This is
762  * overridden in the subclasses since we can often produce the output with
763  * just a portion of the input data.
764  */
765 void 
766 ProcessObject
767 ::GenerateInputRequestedRegion()
768 {
769   std::vector<DataObjectPointer>::size_type idx;
770   for (idx = 0; idx < m_Inputs.size(); ++idx)
771     {
772     if (m_Inputs[idx])
773       {
774       m_Inputs[idx]->SetRequestedRegionToLargestPossibleRegion();
775       }
776     }  
777 }
778
779
780 /**
781  * By default we set all the output requested regions to be the same.
782  */
783 void 
784 ProcessObject
785 ::GenerateOutputRequestedRegion(DataObject *output)
786 {
787   std::vector<DataObjectPointer>::size_type idx;
788   for (idx = 0; idx < m_Outputs.size(); ++idx)
789     {
790     if (m_Outputs[idx] && m_Outputs[idx] != output)
791       {
792       m_Outputs[idx]->SetRequestedRegion(output);
793       }
794     }  
795 }
796
797
798 /**
799  *
800  */
801 void 
802 ProcessObject
803 ::PrepareOutputs()
804 {  
805   unsigned int idx;
806   
807   if (this->GetReleaseDataBeforeUpdateFlag())
808     {
809     for (idx = 0; idx < m_Outputs.size(); idx++)
810       {
811       if (m_Outputs[idx])
812         {
813         m_Outputs[idx]->PrepareForNewData(); 
814         }
815       }
816     }
817 }
818
819
820 /**
821  *
822  */
823 void 
824 ProcessObject
825 ::ReleaseInputs()
826 {  
827   unsigned int idx;
828
829   for (idx = 0; idx < m_Inputs.size(); ++idx)
830     {
831     if (m_Inputs[idx])
832       {
833       if ( m_Inputs[idx]->ShouldIReleaseData() )
834         {
835         m_Inputs[idx]->ReleaseData();
836         }
837       }  
838     }
839 }
840
841
842 /**
843  *
844  */
845 void 
846 ProcessObject
847 ::UpdateOutputData(DataObject *itkNotUsed(output))
848 {
849   std::vector<DataObjectPointer>::size_type idx;
850
851   /**
852    * prevent chasing our tail
853    */
854   if (m_Updating)
855     {
856     return;
857     }
858
859   /**
860    * Prepare all the outputs. This may deallocate previous bulk data.
861    */
862   this->PrepareOutputs();
863
864   /**
865    * Propagate the update call - make sure everything we
866    * might rely on is up-to-date
867    * Must call PropagateRequestedRegion before UpdateOutputData if multiple 
868    * inputs since they may lead back to the same data object.
869    */
870   m_Updating = true;
871   if ( m_Inputs.size() == 1 )
872     {
873     if (m_Inputs[0])
874       {
875       m_Inputs[0]->UpdateOutputData();
876       }
877     }
878   else
879     {
880     for (idx = 0; idx < m_Inputs.size(); ++idx)
881       {
882       if (m_Inputs[idx])
883         {
884         m_Inputs[idx]->PropagateRequestedRegion();
885         m_Inputs[idx]->UpdateOutputData();
886         }
887       }
888     }
889
890   /**
891    * Cache the state of any ReleaseDataFlag's on the inputs. While the
892    * filter is executing, we need to set the ReleaseDataFlag's on the
893    * inputs to false in case the current filter is implemented using a
894    * mini-pipeline (which will try to release the inputs).  After the
895    * filter finishes, we restore the state of the ReleaseDataFlag's
896    * before the call to ReleaseInputs().
897    */
898   this->CacheInputReleaseDataFlags();
899   
900   /**
901    * Tell all Observers that the filter is starting
902    */
903   this->InvokeEvent( StartEvent() );
904
905   /**
906    * GenerateData this object - we have not aborted yet, and our progress
907    * before we start to execute is 0.0.
908    */
909   m_AbortGenerateData = false;
910   m_Progress = 0.0;
911
912   /**
913    * Count the number of required inputs which have been assigned 
914    */
915   unsigned int ninputs = this->GetNumberOfValidRequiredInputs();
916   if (ninputs < m_NumberOfRequiredInputs)
917     {
918     itkExceptionMacro(<< "At least " << m_NumberOfRequiredInputs 
919                       << " inputs are required but only " << ninputs 
920                       << " are specified.");
921     }
922   else
923     {
924     try
925       {
926       this->GenerateData();
927       }
928     catch( ProcessAborted & excp )
929       {
930       excp = excp;
931       this->InvokeEvent( AbortEvent() );
932       this->ResetPipeline();
933       this->RestoreInputReleaseDataFlags();
934       throw ProcessAborted(__FILE__,__LINE__);
935       }
936     catch( ExceptionObject& excp )
937       {
938       this->ResetPipeline();
939       this->RestoreInputReleaseDataFlags();
940       throw excp;
941       }
942     }
943
944   /**
945    * If we ended due to aborting, push the progress up to 1.0 (since
946    * it probably didn't end there)
947    *
948    */
949   if ( m_AbortGenerateData )
950     {
951     this->UpdateProgress(1.0);
952     }
953
954   /**
955    * Notify end event observers
956    */
957   this->InvokeEvent( EndEvent() );
958
959   /**
960    * Now we have to mark the data as up to date.
961    */
962   for (idx = 0; idx < m_Outputs.size(); ++idx)
963     {
964     if (m_Outputs[idx])
965       {
966       m_Outputs[idx]->DataHasBeenGenerated();
967       }
968     }
969   
970   /**
971    * Restore the state of any input ReleaseDataFlags
972    */
973   this->RestoreInputReleaseDataFlags();
974   
975   /**
976    * Release any inputs if marked for release
977    */
978   this->ReleaseInputs();
979   
980   // Mark that we are no longer updating the data in this filter
981   m_Updating = false;
982 }
983
984
985 /**
986  *
987  */
988 void
989 ProcessObject
990 ::CacheInputReleaseDataFlags()
991 {
992   unsigned int idx;
993   
994   m_CachedInputReleaseDataFlags.resize( m_Inputs.size() );
995   for (idx = 0; idx < m_Inputs.size(); ++idx)
996     {
997     if (m_Inputs[idx])
998       {
999       m_CachedInputReleaseDataFlags[idx]=m_Inputs[idx]->GetReleaseDataFlag();
1000       m_Inputs[idx]->ReleaseDataFlagOff();
1001       }
1002     else
1003       {
1004       m_CachedInputReleaseDataFlags[idx] = false;
1005       }
1006     }
1007
1008
1009
1010 /**
1011  *
1012  */
1013 void
1014 ProcessObject
1015 ::RestoreInputReleaseDataFlags()
1016 {
1017   unsigned int idx;
1018   
1019   for (idx = 0;
1020        idx < m_Inputs.size() && idx < m_CachedInputReleaseDataFlags.size();
1021        ++idx)
1022     {
1023     if (m_Inputs[idx])
1024       {
1025       m_Inputs[idx]->SetReleaseDataFlag(m_CachedInputReleaseDataFlags[idx]);
1026       }
1027     }
1028
1029
1030 /**
1031  * Default implementation - copy information from first input to all outputs
1032  */
1033 void 
1034 ProcessObject
1035 ::GenerateOutputInformation()
1036 {
1037   DataObjectPointer input, output;
1038
1039   if (m_Inputs.size() && m_Inputs[0])
1040     {
1041     input = m_Inputs[0];
1042
1043     for (unsigned int idx = 0; idx < m_Outputs.size(); ++idx)
1044       {
1045       output = this->GetOutput(idx);
1046       if (output)
1047         {
1048         output->CopyInformation(input);
1049         }  
1050       }
1051     }
1052 }
1053
1054
1055 /**
1056  *
1057  */
1058 void 
1059 ProcessObject
1060 ::UpdateLargestPossibleRegion()
1061 {
1062   this->UpdateOutputInformation();
1063
1064   if (this->GetOutput(0))
1065     {
1066     this->GetOutput(0)->SetRequestedRegionToLargestPossibleRegion();
1067     this->GetOutput(0)->Update();
1068     }
1069 }
1070
1071
1072 EML
1073 EML
1074 // end namespace itk
1075

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