[Insight-developers] Progress reporting revisited

Kurt Augustine augustine . kurt at mayo . edu
Thu, 22 May 2003 16:50:47 -0500


We have integrated a number of filters in Analyze and incorporated progress
reporting windows that also allow the user to cancel the process if desired.
While the filtering process itself seems to work correctly in all cases, the
same cannot be said for the progress reporting.  This, of course, is not a
new issue but I thought I would give specifics in the hope that they can be
fixed.  The assumption here is that we should be able to handle all progress
reporting the same, regardless of the filter.  Here is what we did:

We instantiate a filter, say ZeroCrossingBasedEdgeDetection and then
instantiate a class we designed called FilterObserver, with the filter as
the only parameter.

typename itk::DanielssonDistanceMapImageFilter<itk::Image<T, 3 >,
itk::Image<T, 3 > >::Pointer myFilter =
itk::DanielssonDistanceMapImageFilter<itk::Image<T, 3 >, itk::Image<T, 3 >
>::New();
FilterObserver watch(myFilter);
   ...
   ...
myFilter->Update();
   ...


Here is FilterObserver:
FilterObserver::FilterObserver(itk::ProcessObject* o)
  {
  m_Process = o;
  itk::SimpleMemberCommand<FilterObserver>::Pointer startFilterCommand;
  itk::SimpleMemberCommand<FilterObserver>::Pointer endFilterCommand;
  itk::SimpleMemberCommand<FilterObserver>::Pointer progressFilterCommand;

  startFilterCommand =    itk::SimpleMemberCommand<FilterObserver>::New();
  endFilterCommand =      itk::SimpleMemberCommand<FilterObserver>::New();
  progressFilterCommand = itk::SimpleMemberCommand<FilterObserver>::New();

  startFilterCommand->SetCallbackFunction(this,
&FilterObserver::StartFilter);
  endFilterCommand->SetCallbackFunction(this, &FilterObserver::EndFilter);
  progressFilterCommand->SetCallbackFunction(this,
&FilterObserver::ShowProgress);
  m_Process->AddObserver(itk::StartEvent(), startFilterCommand);
  m_Process->AddObserver(itk::EndEvent(), endFilterCommand);
  m_Process->AddObserver(itk::ProgressEvent(), progressFilterCommand);
  }

void FilterObserver::ShowProgress()
  {
    if(!someProgressReporterFunction((int)(m_Process->GetProgress()*100)))
    {
	    m_Process->AbortGenerateDataOn(); // clean up and return
	    return;
    }

  }
void FilterObserver::StartFilter()
  {
		someProgressReporterFunction(0);
  }

void FilterObserver::EndFilter()
  {
		someProgressReporterFunction(100);
  }

Where "someProgressReporterFunction(int percent)" can be some function that
reports progress to the user.

Now, this approach works well for some filters, namely:
itkBinaryMinMaxCurvatureFlowImageFilter
itkBinomialBlurImageFilter
itkCurvatureAnisotropicDiffusionImageFilter
itkCurvatureFlowImageFilter
itkDanielssonDistanceMapImageFilter
itkGradientAnisotropicDiffusionImageFilter
itkGradientMagnitudeImageFilter
itkMinMaxCurvatureFlowImageFilter

While others it does not work for:
itkBSplineDecompositionImageFilter
itkDerivativeImageFilter
itkDiscreteGaussianImageFilter
itkGradientMagnitudeRecursiveGaussianImageFilter
itkZeroCrossingBasedEdgeDetectionImageFilter

Some interesting notes that may help in determining problems:  It appears
that only two of the filters from the first list use the ProgressReporter
class and make calls to CompletedPixel().  Most of the rest from the first
list are derived from itkFiniteDiferenceImageFilter, which simply makes
calls to InvokeEvent, specifically this->InvokeEvent(IterationEvent())
followed by this->InvokeEvent(ProgressEvent()).

Three out of the five that do NOT work implement the ProgressReporter class
and are multithreaded.  

So, in general,  it appears that ProgressReporter may have problems with
multithreaded filters (although, one multithreaded case, namely
itkGradientMagnitudeImageFilter appears to work fine).  

Bottom line, ITK filters do not implement progress reporting in a consistent
manner and the chosen report mechanisms do not function at all in some
cases.  As application developers, we obviously need to provide interfaces
that work in a consistent manner.  Therefore, we turn to the filter
developers to help fix the progress reporting bugs (Bill's "code coverage
list" will maybe help identify who).  There certainly may be additional
filters beyond those listed that have the same problem.  We realize this may
seem like a low priority item on some developers' lists but these fixes are
essential to the successful integration of ITK with end-user applications.

Perhaps we can discuss this briefly in the tcon tomorrow.

Thanks (and sorry for the long message) ... Kurt