Page MenuHomePhabricator

[Segmentation] CanHandle functions seem to be inconsistent
Open, LowPublic

Description

While working on T28640: [Segmentation] Add tool checks for dynamic plugin view I realized that different tools provide a CanHandle function which look different and I'm not sure if this makes sense in most cases.
I will list the different functions here so that we can discuss their function-body and the differences.

The CanHandle-function is available in the mitk::Tool-class and is mostly overridden by semi-automatic interactive segmentation tools.

bool mitk::Tool::CanHandle(const BaseData* referenceData, const BaseData* /*workingData*/) const
{
  if (referenceData == nullptr)
    return false;

  return true;
}

The basic mitk::Tool restricts the data that can be handled to reference-data - working-data pairs, where

  • the reference-data is valid

The mitk::AutoSegmentationTool, subclassing the basic mitk::Tool, does not override the CanHandle-function and thus does not restrict the data to be handled more.
The mitk::AutoSegmentationWithPreviewTool, subclassing the mitk::AutoSegmentationTool, does override the CanHandle-function`:

bool mitk::AutoSegmentationWithPreviewTool::CanHandle(const BaseData* referenceData, const BaseData* workingData) const
{
  if (!Superclass::CanHandle(referenceData, workingData))
    return false;

  if (workingData == nullptr)
    return true;

  auto* labelSet = dynamic_cast<const LabelSetImage*>(workingData);

  if (labelSet != nullptr)
    return true;

  auto* image = dynamic_cast<const Image*>(workingData);

  if (image == nullptr)
    return false;

  //if it is a normal image and not a label set image is used as working data
  //it must have the same pixel type as a label set.
  return MakeScalarPixelType< DefaultSegmentationDataType >() == image->GetPixelType();
}

It restricts the data that can be handled to reference-data - working-data pairs, where

  • the working-data is not valid

or

  • the working-data is valid and either a mitk::Image or a mitk::LabelSetImage
  • the mitk::Image has to have a DefaultSegmentationDataType pixel type

Following classes subclass the mitk::AutoSegmentationWithPreviewTool but they restrict the data to be handled more:

bool mitk::PickingTool::CanHandle(const BaseData* referenceData, const BaseData* workingData) const
{
  if (!Superclass::CanHandle(referenceData,workingData))
    return false;

  auto* image = dynamic_cast<const Image*>(referenceData);

  if (image == nullptr)
    return false;

  return true;
}

It restricts the data that can be handled to reference-data - working-data pairs, where

  • the reference-data is a mitk::Image
bool mitk::FastMarchingBaseTool::CanHandle(const BaseData* referenceData, const BaseData* workingData) const
{
  if(!Superclass::CanHandle(referenceData, workingData))
    return false;

  if (referenceData == nullptr)
    return false;

  auto *image = dynamic_cast<const Image *>(referenceData);

  if (image == nullptr)
    return false;

  if (image->GetDimension() < 3)
    return false;

  return true;
}

It restricts the data that can be handled to reference-data - working-data pairs, where

  • the reference-data is valid (which is already guaranteed by the base-class mitk::Tool)
  • the reference-data is a mitk::Image
  • the reference image is not a 2D image

The mitk::AdaptiveRegionGrowingTool directly subclasses the mitk::AutoSegmentationTool but it restricts the data to be handled more:

bool mitk::AdaptiveRegionGrowingTool::CanHandle(const BaseData* referenceData, const BaseData* /*workingData*/) const
{
  if (referenceData == nullptr)
    return false;

  auto *image = dynamic_cast<const Image *>(referenceData);

  if (image == nullptr)
    return false;

  if (image->GetDimension() < 3)
    return false;

  if (image->GetTimeSteps() > 1) //release quickfix for T28275
    return false;

  return true;
}

It restricts the data that can be handled to reference-data - working-data pairs, where

  • the reference-data is valid (which is already guaranteed by the base-class mitk::Tool, but the function does not call Superclass::CanHandle)
  • the reference-data is a mitk::Image
  • the reference image is not a 2D image
  • the reference image is not a 4D image

There are some problems / inconsistencies with these different implementations so I will address them in the comments.

Event Timeline

kalali triaged this task as Normal priority.Feb 22 2022, 5:10 PM
kalali created this task.

mitk::Tool::CanHandle:

In T28989, @kalali wrote:

The basic mitk::Tool restricts the data that can be handled to reference-data - working-data pairs, where

  • the reference-data is valid

Why is it not required for the working-data to be valid? This is a requirement for all following CanHandle-functions (working data needs to be an mitk::LabelSetImage or an mitk::Image) that override the basic function, so why not put it in the basic class function?

mitk::AutoSegmentationWithPreviewTool::CanHandle:

In T28989, @kalali wrote:

It restricts the data that can be handled to reference-data - working-data pairs, where

  • the working-data is not valid

or

  • the working-data is valid and either an mitk::Image or an mitk::LabelSetImage
  • the mitk::Image has to have a DefaultSegmentationDataType pixel type

What sense does it make to enable a tool if the working-data is not valid? The segmentation-view does not even enable the whole manual tool selection box (2D and 3D) if not both a reference node and a working node are selected.

Why is this check not directly put into the mitk::AutoSegmentationTool, which is the base class of the mitk::AutoSegmentationWithPreviewTool?

mitk::PickingTool::CanHandle:

In T28989, @kalali wrote:

It restricts the data that can be handled to reference-data - working-data pairs, where

  • the reference-data is a mitk::Image

Why does the reference-data have to be an mitk::Image only in the PickingTool-case (and in all following cases), but not in the base-class itself? In what scenario can the reference data be something else than an mitk::Image?

mitk::FastMarchingBaseTool::CanHandle:

In T28989, @kalali wrote:

It restricts the data that can be handled to reference-data - working-data pairs, where

  • the reference-data is valid (which is already guaranteed by the base-class mitk::Tool)
  • the reference-data is a mitk::Image
  • the reference image is not a 2D image

As already stated, the check for a valid reference data is redundant.
Except for the dimensionality-check, everything else is equal to the mitk::PickingTool, so why not put everything else into the common base-class mitk::AutoSegmentationWithPreviewTool or even mitk::AutoSegmentationTool?
This would then also affect other tools, that inherit these classes but do not provide a custom CanHandle-function (e.g. Watershed, Otsu, nnUNet, BinaryThreshold).
That leads me to the question: Why should e.g. the threshold-tool be handled differently than the fast marching tool (in terms of valid data / image input)?

mitk::AdaptiveRegionGrowingTool:
This class has not been refactored so it implements its own CanHandle-function but this is similar to mitk::FastMarchingBaseTool::CanHandle and could be replaced by a common base class implementation (except for the timestep / check-for-4D part), which is custom for this tool because of T28275: [Segmentation] AdaptiveRegionGrowingTool must be refactored / 4D Segmentation returns error message when point is not on the correct timestep.

kalali lowered the priority of this task from Normal to Low.Apr 20 2022, 5:02 PM