Orfeo Toolbox  3.16
itkProcessObject.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkProcessObject.cxx,v $
5  Language: C++
6  Date: $Date: 2009-03-03 15:08:01 $
7  Version: $Revision: 1.75 $
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  PURPOSE. See the above copyright notices for more information.
18 
19 =========================================================================*/
20 #include "itkProcessObject.h"
21 #include "itkDataObject.h"
22 #include "itkObjectFactory.h"
23 #include "itkCommand.h"
24 
25 #include <functional>
26 #include <algorithm>
27 
28 namespace itk
29 {
30 
36 {
37  m_NumberOfRequiredInputs = 0;
38 
39  m_NumberOfRequiredOutputs = 0;
40 
41  m_AbortGenerateData = false;
42  m_Progress = 0.0f;
43  m_Updating = false;
44 
45  m_Threader = MultiThreader::New();
46  m_NumberOfThreads = m_Threader->GetNumberOfThreads();
47 
48  m_ReleaseDataBeforeUpdateFlag = true;
49 }
50 
59 ::MakeOutput(unsigned int)
60 {
61  return static_cast<DataObject*>(DataObject::New().GetPointer());
62 }
63 
70 {
71  // Tell each output that we are going away. If other objects have a
72  // reference to one of these outputs, the data object will not be deleted
73  // when the process object is deleted. However, the data object's source
74  // will still point back to the now nonexistent process object if we do not
75  // clean things up now.
76  unsigned int idx;
77  for (idx = 0; idx < m_Outputs.size(); ++idx)
78  {
79  if (m_Outputs[idx])
80  {
81  // let the output know we no longer want to associate with the object
82  m_Outputs[idx]->DisconnectSource(this, idx);
83  // let go of our reference to the data object
84  m_Outputs[idx] = 0;
85  }
86  }
87 }
88 
89 //typedef DataObject *DataObjectPointer;
90 
94 void
96 ::SetNumberOfInputs(unsigned int num)
97 {
98  // in case nothing has changed.
99  if (num == m_Inputs.size())
100  {
101  return;
102  }
103  m_Inputs.resize(num);
104  this->Modified();
105 }
106 
113 {
115  if (m_NumberOfRequiredInputs < m_Inputs.size())
116  {
117  num = m_NumberOfRequiredInputs;
118  }
119  else
120  {
121  num = m_Inputs.size();
122  }
123  // count the number of non-null inputs
124  // this used to use std::count_if, but that function object
125  // did not work correctly with SunPro CC 5.6.
126  int count = 0;
127  for(std::vector<DataObjectPointer>::const_iterator i = m_Inputs.begin();
128  i < (m_Inputs.begin() + num); ++i)
129  {
130  if((*i).IsNotNull())
131  {
132  count++;
133  }
134  }
135  return count;
136 }
137 
142 void
145 {
147 
148  this->Modified();
149 
150  for (idx = 0; idx < m_Inputs.size(); ++idx)
151  {
152  if (!m_Inputs[idx])
153  {
154  m_Inputs[idx] = input;
155  return;
156  }
157  }
158 
159  this->SetNumberOfInputs( static_cast<int>( m_Inputs.size() + 1 ) );
160  m_Inputs[ static_cast<int>( m_Inputs.size() ) - 1] = input;
161 }
162 
163 
171 void
174 {
175  if (!input)
176  {
177  return;
178  }
179 
180  // find the input in the list of inputs
181  DataObjectPointerArray::iterator pos =
182  std::find(m_Inputs.begin(), m_Inputs.end(), input);
183 
184  if(pos == m_Inputs.end())
185  {
186  itkDebugMacro("tried to remove an input that was not in the list");
187  return;
188  }
189 
190  // Set the position in the m_Inputs containing input to 0
191  *pos = 0;
192 
193  // if that was the last input, then shrink the list
194  if (pos == m_Inputs.end() - 1 )
195  {
196  this->SetNumberOfInputs( static_cast<int>( m_Inputs.size() ) - 1);
197  }
198 
199  this->Modified();
200 }
201 
208 void
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 
232 void
235 {
236  m_Inputs.push_back(const_cast<DataObject*>(input));
237  this->Modified();
238 }
239 
243 void
246 {
247  if (!m_Inputs.empty())
248  {
249  m_Inputs.pop_back();
250  this->Modified();
251  }
252 }
253 
257 void
260 {
261  // add an empty element to the end of the vector to make sure that
262  // we have enough space for the copy
263  m_Inputs.push_back(0);
264 
265  // shift the current inputs down by one place
266  std::copy_backward(m_Inputs.begin(), m_Inputs.end()-1,
267  m_Inputs.end());
268 
269  // put in the new input in the front
270  m_Inputs[0] = const_cast<DataObject*>(input);
271 
272  this->Modified();
273 }
274 
278 void
281 {
282  if (!m_Inputs.empty())
283  {
284  std::copy(m_Inputs.begin()+1, m_Inputs.end(),
285  m_Inputs.begin());
286 
287  m_Inputs.pop_back();
288  this->Modified();
289  }
290 }
291 
292 void
295 {
296  if (!output)
297  {
298  return;
299  }
300 
301  // find the input in the list of inputs
302  DataObjectPointerArray::iterator pos =
303  std::find(m_Outputs.begin(), m_Outputs.end(), output);
304 
305  if(pos == m_Outputs.end())
306  {
307  itkDebugMacro("tried to remove an output that was not in the list");
308  return;
309  }
310 
311  // let the output know we no longer want to associate with the object
312  (*pos)->DisconnectSource(this, pos - m_Outputs.begin());
313  // let go of our reference to the data object
314  *pos = 0;
315 
316  // if that was the last output, then shrink the list
317  if (pos == m_Outputs.end() - 1 )
318  {
319  this->SetNumberOfOutputs( static_cast<int>( m_Outputs.size() ) - 1);
320  }
321 
322  this->Modified();
323 }
324 
325 
331 void
333 ::SetNthOutput(unsigned int idx, DataObject *output)
334 {
335  // does this change anything?
336  if ( idx < m_Outputs.size() && output == m_Outputs[idx])
337  {
338  return;
339  }
340 
341  // Expand array if necessary.
342  if (idx >= m_Outputs.size())
343  {
344  this->SetNumberOfOutputs(idx + 1);
345  }
346 
347  // Keep a handle to the original output and disconnect the old output from
348  // the pipeline
349  DataObjectPointer oldOutput;
350  if ( m_Outputs[idx] )
351  {
352  oldOutput = m_Outputs[idx];
353  m_Outputs[idx]->DisconnectSource(this, idx);
354  }
355 
356  if (output)
357  {
358  output->ConnectSource(this, idx);
359  }
360  // save the current reference (which releases the previous reference)
361  m_Outputs[idx] = output;
362 
363  // if we are clearing an output, we need to create a new blank output
364  // so we are prepared for the next Update(). this copies the requested
365  // region ivar
366  if (!m_Outputs[idx])
367  {
368  itkDebugMacro( " creating new output object." );
369  DataObjectPointer newOutput = this->MakeOutput(idx);
370  this->SetNthOutput(idx, newOutput);
371 
372  // If we had an output object before, copy the requested region
373  // ivars and release data flag to the the new output
374  if (oldOutput)
375  {
376  newOutput->SetRequestedRegion( oldOutput );
377  newOutput->SetReleaseDataFlag( oldOutput->GetReleaseDataFlag() );
378  }
379  }
380 
381  this->Modified();
382 }
383 
388 void
391 {
392  unsigned int idx;
393 
394  for (idx = 0; idx < m_Outputs.size(); ++idx)
395  {
396  if ( m_Outputs[idx].IsNull() )
397  {
398  m_Outputs[idx] = output;
399 
400  if (output)
401  {
402  output->ConnectSource(this, idx);
403  }
404  this->Modified();
405 
406  return;
407  }
408  }
409 
410  this->SetNumberOfOutputs( static_cast<int>( m_Outputs.size() ) + 1);
411  m_Outputs[ static_cast<int>( m_Outputs.size() ) - 1] = output;
412  if (output)
413  {
414  output->ConnectSource(this, static_cast<int>( m_Outputs.size() ) - 1 );
415  }
416  this->Modified();
417 }
418 
422 void
424 ::SetNumberOfOutputs(unsigned int num)
425 {
426 
427  // in case nothing has changed.
428  if (num == m_Outputs.size())
429  {
430  return;
431  }
432  m_Outputs.resize(num);
433  this->Modified();
434 }
435 
436 
440 DataObject *
442 ::GetOutput(unsigned int i)
443 {
444  if (m_Outputs.size() < i+1)
445  {
446  return NULL;
447  }
448 
449  return m_Outputs[i].GetPointer();
450 }
451 
452 const DataObject *
454 ::GetOutput(unsigned int i) const
455 {
456  if (m_Outputs.size() < i+1)
457  {
458  return NULL;
459  }
460 
461  return m_Outputs[i].GetPointer();
462 }
463 
464 
468 DataObject *
470 ::GetInput(unsigned int i)
471 {
472  if (m_Inputs.size() < i+1)
473  {
474  return NULL;
475  }
476 
477  return m_Inputs[i].GetPointer();
478 }
479 
480 const DataObject *
482 ::GetInput(unsigned int i) const
483 {
484  if (m_Inputs.size() < i+1)
485  {
486  return NULL;
487  }
488 
489  return m_Inputs[i].GetPointer();
490 }
491 
492 
498 void
500 ::UpdateProgress(float amount)
501 {
502  m_Progress = amount;
503  this->InvokeEvent( ProgressEvent() );
504 }
505 
506 
510 bool
513 {
514  if (this->GetOutput(0))
515  {
516  return this->GetOutput(0)->GetReleaseDataFlag();
517  }
518  itkWarningMacro(<<"Output doesn't exist!");
519  return false;
520 }
521 
522 
526 void
529 {
530  unsigned int idx;
531 
532  for (idx = 0; idx < m_Outputs.size(); idx++)
533  {
534  if (m_Outputs[idx])
535  {
536  m_Outputs[idx]->SetReleaseDataFlag(val);
537  }
538  }
539 }
540 
541 
545 void
547 ::PrintSelf(std::ostream& os, Indent indent) const
548 {
549  Superclass::PrintSelf(os,indent);
550 
551  os << indent << "Number Of Required Inputs: "
552  << m_NumberOfRequiredInputs << std::endl;
553 
554  os << indent << "Number Of Required Outputs: "
555  << m_NumberOfRequiredOutputs << std::endl;
556 
557  os << indent << "Number Of Threads: "
558  << m_NumberOfThreads << std::endl;
559 
560  os << indent << "ReleaseDataFlag: "
561  << (this->GetReleaseDataFlag() ? "On" : "Off") << std::endl;
562 
563  os << indent << "ReleaseDataBeforeUpdateFlag: "
564  << (m_ReleaseDataBeforeUpdateFlag ? "On" : "Off") << std::endl;
565 
566  if ( m_Inputs.size())
567  {
569  for (idx = 0; idx < m_Inputs.size(); ++idx)
570  {
571  os << indent << "Input " << static_cast<int>( idx );
572  os << ": (" << m_Inputs[idx].GetPointer() << ")\n";
573  }
574  }
575  else
576  {
577  os << indent <<"No Inputs\n";
578  }
579  if ( m_Outputs.size())
580  {
582  for (idx = 0; idx < m_Outputs.size(); ++idx)
583  {
584  os << indent << "Output " << static_cast<int>( idx );
585  os << ": (" << m_Outputs[idx].GetPointer() << ")\n";
586  }
587  }
588  else
589  {
590  os << indent <<"No Output\n";
591  }
592 
593  os << indent << "AbortGenerateData: " << (m_AbortGenerateData ? "On\n" : "Off\n");
594  os << indent << "Progress: " << m_Progress << "\n";
595 
596  os << indent << "Multithreader: " << std::endl;
597  m_Threader->PrintSelf(os, indent.GetNextIndent());
598 }
599 
609 void
612 {
613  if (this->GetOutput(0))
614  {
615  this->GetOutput(0)->Update();
616  }
617 }
618 
619 void
622 {
623  if (this->GetOutput(0))
624  {
625  this->GetOutput(0)->ResetPipeline();
626  }
627 }
628 
629 void
632 {
633  //
634  // Reset this object.
635  //
636  // Clear the updating flag.
637  m_Updating = 0;
638 
639  //
640  // Loop through the inputs
641  //
642  unsigned int idx;
643  DataObject::Pointer input;
644  for (idx = 0; idx < m_Inputs.size(); ++idx)
645  {
646  if (m_Inputs[idx])
647  {
648  input = m_Inputs[idx];
649 
653  input->PropagateResetPipeline();
654  }
655  }
656 }
657 
658 
662 void
665 {
666  unsigned long t1, t2;
668  DataObject *input;
669  DataObject *output;
670 
674  if ( m_Updating )
675  {
682  this->Modified();
683  return;
684  }
685 
692  t1 = this->GetMTime();
693 
697  for (idx = 0; idx < m_Inputs.size(); ++idx)
698  {
699  if (m_Inputs[idx])
700  {
701  input = m_Inputs[idx];
702 
706  m_Updating = true;
707  input->UpdateOutputInformation();
708  m_Updating = false;
709 
714  t2 = input->GetPipelineMTime();
715 
716  if (t2 > t1)
717  {
718  t1 = t2;
719  }
720 
725  t2 = input->GetMTime();
726  if (t2 > t1)
727  {
728  t1 = t2;
729  }
730  }
731  }
732 
740  if (t1 > m_OutputInformationMTime.GetMTime())
741  {
742  for (idx = 0; idx < m_Outputs.size(); ++idx)
743  {
744  output = this->GetOutput( static_cast<int>( idx ) );
745  if (output)
746  {
747  output->SetPipelineMTime(t1);
748  }
749  }
750 
751  this->GenerateOutputInformation();
752 
756  m_OutputInformationMTime.Modified();
757  }
758 }
759 
760 
764 void
767 {
771  if (m_Updating)
772  {
773  return;
774  }
775 
783  this->EnlargeOutputRequestedRegion( output );
784 
792  this->GenerateOutputRequestedRegion( output );
793 
802  this->GenerateInputRequestedRegion();
803 
808  m_Updating = true;
810  for (idx = 0; idx < m_Inputs.size(); ++idx)
811  {
812  if (m_Inputs[idx])
813  {
814  m_Inputs[idx]->PropagateRequestedRegion();
815  }
816  }
817  m_Updating = false;
818 }
819 
820 
826 void
829 {
831  for (idx = 0; idx < m_Inputs.size(); ++idx)
832  {
833  if (m_Inputs[idx])
834  {
835  m_Inputs[idx]->SetRequestedRegionToLargestPossibleRegion();
836  }
837  }
838 }
839 
840 
844 void
847 {
849  for (idx = 0; idx < m_Outputs.size(); ++idx)
850  {
851  if (m_Outputs[idx] && m_Outputs[idx] != output)
852  {
853  m_Outputs[idx]->SetRequestedRegion(output);
854  }
855  }
856 }
857 
858 
862 void
865 {
866  unsigned int idx;
867 
868  if (this->GetReleaseDataBeforeUpdateFlag())
869  {
870  for (idx = 0; idx < m_Outputs.size(); idx++)
871  {
872  if (m_Outputs[idx])
873  {
874  m_Outputs[idx]->PrepareForNewData();
875  }
876  }
877  }
878 }
879 
880 
884 void
887 {
888  unsigned int idx;
889 
890  for (idx = 0; idx < m_Inputs.size(); ++idx)
891  {
892  if (m_Inputs[idx])
893  {
894  if ( m_Inputs[idx]->ShouldIReleaseData() )
895  {
896  m_Inputs[idx]->ReleaseData();
897  }
898  }
899  }
900 }
901 
902 
906 void
908 ::UpdateOutputData(DataObject *itkNotUsed(output))
909 {
911 
915  if (m_Updating)
916  {
917  return;
918  }
919 
923  this->PrepareOutputs();
924 
931  m_Updating = true;
932  if ( m_Inputs.size() == 1 )
933  {
934  if (m_Inputs[0])
935  {
936  m_Inputs[0]->UpdateOutputData();
937  }
938  }
939  else
940  {
941  for (idx = 0; idx < m_Inputs.size(); ++idx)
942  {
943  if (m_Inputs[idx])
944  {
945  m_Inputs[idx]->PropagateRequestedRegion();
946  m_Inputs[idx]->UpdateOutputData();
947  }
948  }
949  }
950 
959  this->CacheInputReleaseDataFlags();
960 
964  this->InvokeEvent( StartEvent() );
965 
970  m_AbortGenerateData = false;
971  m_Progress = 0.0f;
972 
976  DataObjectPointerArraySizeType ninputs = this->GetNumberOfValidRequiredInputs();
977  if (ninputs < m_NumberOfRequiredInputs)
978  {
979  itkExceptionMacro(<< "At least " << m_NumberOfRequiredInputs
980  << " inputs are required but only " << ninputs
981  << " are specified.");
982  }
983  else
984  {
985  try
986  {
987  this->GenerateData();
988  }
989  catch( ProcessAborted & excp )
990  {
991  this->InvokeEvent( AbortEvent() );
992  this->ResetPipeline();
993  this->RestoreInputReleaseDataFlags();
994  throw excp;
995  }
996  catch( ExceptionObject& excp )
997  {
998  this->ResetPipeline();
999  this->RestoreInputReleaseDataFlags();
1000  throw excp;
1001  }
1002  }
1003 
1009  if ( m_AbortGenerateData )
1010  {
1011  this->UpdateProgress(1.0f);
1012  }
1013 
1017  this->InvokeEvent( EndEvent() );
1018 
1022  for (idx = 0; idx < m_Outputs.size(); ++idx)
1023  {
1024  if (m_Outputs[idx])
1025  {
1026  m_Outputs[idx]->DataHasBeenGenerated();
1027  }
1028  }
1029 
1033  this->RestoreInputReleaseDataFlags();
1034 
1038  this->ReleaseInputs();
1039 
1040  // Mark that we are no longer updating the data in this filter
1041  m_Updating = false;
1042 }
1043 
1044 
1048 void
1051 {
1052  unsigned int idx;
1053 
1054  m_CachedInputReleaseDataFlags.resize( m_Inputs.size() );
1055  for (idx = 0; idx < m_Inputs.size(); ++idx)
1056  {
1057  if (m_Inputs[idx])
1058  {
1059  m_CachedInputReleaseDataFlags[idx]=m_Inputs[idx]->GetReleaseDataFlag();
1060  m_Inputs[idx]->ReleaseDataFlagOff();
1061  }
1062  else
1063  {
1064  m_CachedInputReleaseDataFlags[idx] = false;
1065  }
1066  }
1067 }
1068 
1069 
1073 void
1076 {
1077  unsigned int idx;
1078 
1079  for (idx = 0;
1080  idx < m_Inputs.size() && idx < m_CachedInputReleaseDataFlags.size();
1081  ++idx)
1082  {
1083  if (m_Inputs[idx])
1084  {
1085  m_Inputs[idx]->SetReleaseDataFlag(m_CachedInputReleaseDataFlags[idx]);
1086  }
1087  }
1088 }
1089 
1093 void
1096 {
1097  DataObjectPointer input, output;
1098 
1099  if (m_Inputs.size() && m_Inputs[0])
1100  {
1101  input = m_Inputs[0];
1102 
1103  for (unsigned int idx = 0; idx < m_Outputs.size(); ++idx)
1104  {
1105  output = this->GetOutput(idx);
1106  if (output)
1107  {
1108  output->CopyInformation(input);
1109  }
1110  }
1111  }
1112 }
1113 
1114 
1118 void
1121 {
1122  this->UpdateOutputInformation();
1123 
1124  if (this->GetOutput(0))
1125  {
1126  this->GetOutput(0)->SetRequestedRegionToLargestPossibleRegion();
1127  this->GetOutput(0)->Update();
1128  }
1129 }
1130 
1131 } // end namespace itk

Generated at Sun Feb 3 2013 00:00:02 for Orfeo Toolbox with doxygen 1.8.1.1