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 #ifndef itkSimpleFilterWatcher_h 19 #define itkSimpleFilterWatcher_h 20 21 #include "itkCommand.h" 22 #include "itkProcessObject.h" 23 #include "itkTimeProbe.h" 24 25 namespace itk 26 { 27 /** \class SimpleFilterWatcher 28 * \brief Simple mechanism for monitoring the pipeline events of a filter 29 * and reporting these events to std::cout. 30 * 31 * SimpleFilterWatcher provides a simple mechanism for monitoring the 32 * execution of filter. SimpleFilterWatcher is a stack-based object 33 * which takes a pointer to a ProcessObject at constructor 34 * time. SimpleFilterWatcher creates a series of commands that are 35 * registered as observers to the specified ProcessObject. The events 36 * monitored are: 37 * 38 * StartEvent 39 * EndEvent 40 * ProgressEvent 41 * IterationEvent 42 * AbortEvent 43 * 44 * The callbacks routines registered for these events emit a simple 45 * message to std::cout. 46 * 47 * Example of use: 48 * 49 * using FilterType = itk::BinaryThresholdImageFilter<ImageType>; 50 * FilterType::Pointer thresholdFilter = FilterType::New(); 51 * 52 * SimpleFilterWatcher watcher(thresholdFilter, "Threshold"); 53 * 54 * The second argument to the constructor to SimpleFilterWatcher is an 55 * optional string that is prepended to the event messages. This 56 * allows the user to associate the emitted messages to a particular 57 * filter/variable. 58 * 59 * \todo Allow any stream object to be used for the output (not just std::cout) 60 * 61 * \ingroup ITKCommon 62 * 63 * \wiki 64 * \wikiexample{Utilities/SimpleFilterWatcher,Monitor a filter} 65 * \endwiki 66 */ 67 class ITKCommon_EXPORT SimpleFilterWatcher 68 { 69 public: 70 /** Constructor. Takes a ProcessObject to monitor and an optional 71 * comment string that is prepended to each event message. */ 72 SimpleFilterWatcher(itk::ProcessObject *o, const char *comment = ""); 73 74 /** Copy constructor */ 75 SimpleFilterWatcher(const SimpleFilterWatcher &); 76 77 /** Default constructor. Only provided so that you can have 78 * std::vectors of SimpleFilterWatchers. */ 79 SimpleFilterWatcher(); 80 81 /** operator= */ 82 SimpleFilterWatcher & operator=(const SimpleFilterWatcher &); 83 84 /** Destructor. */ 85 virtual ~SimpleFilterWatcher(); 86 87 /** Method to get the name of the class be monitored by this 88 * SimpleFilterWatcher */ GetNameOfClass()89 const char * GetNameOfClass() 90 { 91 return ( m_Process ? m_Process->GetNameOfClass() : "None" ); 92 } 93 94 /** Methods to control the verbosity of the messages. Quiet 95 * reporting limits the information emitted at a ProgressEvent. */ QuietOn()96 void QuietOn() { m_Quiet = true; } QuietOff()97 void QuietOff() { m_Quiet = false; } 98 99 /** Methods to use to test the AbortEvent of the a filter. If 100 * TestAbort is on, the filter being watched will be aborted when 101 * the progress reaches 30%. */ TestAbortOn()102 void TestAbortOn() { m_TestAbort = true; } TestAbortOff()103 void TestAbortOff() { m_TestAbort = false; } 104 105 /** Methods to access member data */ 106 /** Get a pointer to the process object being watched. */ GetProcess()107 ProcessObject * GetProcess() { return m_Process.GetPointer(); } 108 109 /** Set/Get the steps completed. */ SetSteps(int val)110 void SetSteps(int val) { m_Steps = val; } GetSteps()111 int GetSteps() { return m_Steps; } 112 113 /** Set/Get the number of iterations completed. */ SetIterations(int val)114 void SetIterations(int val) { m_Iterations = val; } GetIterations()115 int GetIterations() { return m_Iterations; } 116 117 /** Set/Get the quiet mode boolean. If true, verbose progress is 118 * reported. */ SetQuiet(bool val)119 void SetQuiet(bool val) { m_Quiet = val; } GetQuiet()120 bool GetQuiet() { return m_Quiet; } 121 122 /** Get the comment for the watcher. */ GetComment()123 std::string GetComment() { return m_Comment; } 124 125 /** Get a reference to the TimeProbe */ GetTimeProbe()126 TimeProbe & GetTimeProbe() { return m_TimeProbe; } 127 128 protected: 129 130 /** Callback method to show the ProgressEvent */ ShowProgress()131 virtual void ShowProgress() 132 { 133 if ( m_Process ) 134 { 135 m_Steps++; 136 if ( !m_Quiet ) 137 { 138 std::cout << " | " << m_Process->GetProgress() << std::flush; 139 if ( ( m_Steps % 10 ) == 0 ) 140 { 141 std::cout << std::endl; 142 } 143 } 144 if ( m_TestAbort ) 145 { 146 if ( m_Process->GetProgress() > .03 ) 147 { 148 m_Process->AbortGenerateDataOn(); 149 } 150 } 151 } 152 } 153 154 /** Create commands for different event types. */ 155 void CreateCommands(); 156 157 /** Remove observers we have on the process object. */ 158 void RemoveObservers(); 159 160 /** The common code for copying this class. */ 161 void DeepCopy(const SimpleFilterWatcher & watch); 162 163 /** Callback method to show the AbortEvent */ ShowAbort()164 virtual void ShowAbort() 165 { 166 std::cout << std::endl << "-------Aborted" << std::endl << std::flush; 167 } 168 169 /** Callback method to show the IterationEvent */ ShowIteration()170 virtual void ShowIteration() 171 { 172 std::cout << " #" << std::flush; 173 m_Iterations++; 174 } 175 176 /** Callback method to show the StartEvent */ StartFilter()177 virtual void StartFilter() 178 { 179 m_Steps = 0; 180 m_Iterations = 0; 181 m_TimeProbe.Start(); 182 std::cout << "-------- Start " 183 << ( m_Process.GetPointer() ? m_Process->GetNameOfClass() : "None" ) 184 << " \"" << m_Comment << "\" "; 185 if ( !m_Quiet ) 186 { 187 if ( m_Process ) 188 { 189 std::cout << m_Process; 190 } 191 else 192 { 193 std::cout << "Null"; 194 } 195 } 196 std::cout << ( m_Quiet ? "Progress Quiet " : "Progress " ) 197 << std::flush; 198 } 199 200 /** Callback method to show the EndEvent */ EndFilter()201 virtual void EndFilter() 202 { 203 m_TimeProbe.Stop(); 204 std::cout << std::endl << "Filter took " 205 << m_TimeProbe.GetMean() 206 << " seconds."; 207 std::cout << std::endl 208 << "-------- End " 209 << ( m_Process.GetPointer() ? m_Process->GetNameOfClass() : "None" ) 210 << " \"" << m_Comment << "\" " << std::endl; 211 if ( !m_Quiet ) 212 { 213 if ( m_Process ) 214 { 215 std::cout << m_Process; 216 } 217 else 218 { 219 std::cout << "None"; 220 } 221 std::cout << std::flush; 222 } 223 if ( m_Steps < 1 ) 224 { 225 itkExceptionMacro ("Filter does not have progress."); 226 } 227 } 228 229 private: 230 TimeProbe m_TimeProbe; 231 int m_Steps{0}; 232 int m_Iterations{0}; 233 bool m_Quiet{false}; 234 bool m_TestAbort{false}; 235 std::string m_Comment; 236 itk::ProcessObject::Pointer m_Process; 237 238 using CommandType = SimpleMemberCommand< SimpleFilterWatcher >; 239 CommandType::Pointer m_StartFilterCommand; 240 CommandType::Pointer m_EndFilterCommand; 241 CommandType::Pointer m_ProgressFilterCommand; 242 CommandType::Pointer m_IterationFilterCommand; 243 CommandType::Pointer m_AbortFilterCommand; 244 245 unsigned long m_StartTag{0}; 246 unsigned long m_EndTag{0}; 247 unsigned long m_ProgressTag{0}; 248 unsigned long m_IterationTag{0}; 249 unsigned long m_AbortTag{0}; 250 }; 251 } // end namespace itk 252 253 #endif 254