FAST-Pathology: The pipeline is throwing Segmentation Fault (Core Dumped) while trying to replicate BACH classification pipeline in Python which is working if I try to process same file via front end application

I am getting Segmentation Fault (Core Dumped) at

classification = fast.SegmentationNetwork.create(
        model.paths[0] + '/pw_classification_bach_mobilenet_v2.onnx',
        scaleFactor=1./255.
    ).connect(generator)

This is the entire script which I was trying to replicate in Python Original

PipelineName "BACH Classification"
PipelineDescription "Patch-wise image classification model trained on data from the 2018 breast cancer histology (BACH) challenge: https://iciar2018-challenge.grand-challenge.org/"
PipelineInputData WSI "Whole-slide image"
PipelineOutputData heatmap stitcher 0
Attribute classes "Normal;Benign;In Situ Carcinoma;Invasive Carcinoma"

### Processing chain

ProcessObject tissueSeg TissueSegmentation
Attribute threshold 85
Input 0 WSI

ProcessObject patch PatchGenerator
Attribute patch-size 512 512
Attribute patch-magnification 20
Attribute patch-overlap 0.0
Attribute mask-threshold 0.05
Input 0 WSI
Input 1 tissueSeg 0

ProcessObject network NeuralNetwork
Attribute scale-factor 0.00392156862
Attribute model "$CURRENT_PATH$/../bach-model/pw_classification_bach_mobilenet_v2.onnx"
Input 0 patch 0

ProcessObject stitcher PatchStitcher
Input 0 network 0

### Renderers
Renderer imgRenderer ImagePyramidRenderer
Input 0 WSI

Renderer heatmap HeatmapRenderer
Attribute interpolation false
Attribute hidden-channels 0
Attribute channel-colors "0" "green" "1" "green" "2" "magenta" "3" "red"
Input 0 stitcher 0

Python

import fast
model = fast.DataHub().download('bach-model')

image_name = "TIFF_pyramid.tiff"
importer = fast.WholeSlideImageImporter\
    .create(image_name)

tissueSegmentation = fast.TissueSegmentation.create(threshold=85)\
    .connect(importer)

generator = fast.PatchGenerator.create(
        512, 512,
        magnification=20,
        overlapPercent=0,
        maskThreshold= 0.05
    ).connect(importer)\
    .connect(1, tissueSegmentation)

classification = fast.SegmentationNetwork.create(
        model.paths[0] + '/pw_classification_bach_mobilenet_v2.onnx',
        scaleFactor=1./255.
    ).connect(generator)

stitcher = fast.PatchStitcher.create()\
    .connect(classification)

finished = fast.RunUntilFinished.create()\
    .connect(stitcher)

exporter = fast.TIFFImagePyramidExporter.create(f'{image_name}_processed.tiff')\
    .connect(finished)\
    .run()

exporter = fast.TIFFImagePyramidExporter.create(f'{image_name}_heatmap.tiff')\
    .connect(tissueSegmentation)\
    .run()
    
renderer = fast.ImagePyramidRenderer.create()\
    .connect(importer)

heatmap = fast.HeatmapRenderer.create(useInterpolation=False, channelColors=[(0, "green"),(1, "green"),(2, "magenta"),(3, "red")])\
    .connect(stitcher)

fast.SimpleWindow2D.create()\
    .connect(renderer)\
    .connect(heatmap)\
    .run()

About this issue

  • Original URL
  • State: closed
  • Created 6 months ago
  • Reactions: 1
  • Comments: 20 (10 by maintainers)

Most upvoted comments

You have some other mistakes as well, this works on my side:

import fast
model = fast.DataHub().download('bach-model')

image_name = "TIFF_pyramid.tiff"
importer = fast.WholeSlideImageImporter\
    .create(image_name)

tissueSegmentation = fast.TissueSegmentation.create(threshold=85)\
    .connect(importer)

generator = fast.PatchGenerator.create(
        512, 512,
        magnification=20,
        overlapPercent=0,
        maskThreshold= 0.05
    ).connect(importer)\
    .connect(1, tissueSegmentation)

classification = fast.NeuralNetwork.create(
        model.paths[0] + '/pw_classification_bach_mobilenet_v2.onnx',
        scaleFactor=1./255.
    ).connect(generator)

stitcher = fast.PatchStitcher.create()\
    .connect(classification)

finished = fast.RunUntilFinished.create()\
    .connect(stitcher)

renderer = fast.ImagePyramidRenderer.create()\
    .connect(importer)

heatmap = fast.HeatmapRenderer.create(useInterpolation=False, channelColors={0: fast.Color.Green(), 1: fast.Color.Green(), 2: fast.Color.Magenta(),3: fast.Color.Red()})\
    .connect(stitcher)

fast.SimpleWindow2D.create()\
    .connect(renderer)\
    .connect(heatmap)\
    .run()

# Export at the end
fast.TIFFImagePyramidExporter.create(f'{image_name}_processed.tiff')\
    .connect(finished).run()

fast.TIFFImagePyramidExporter.create(f'{image_name}_heatmap.tiff')\
    .connect(tissueSegmentation).run()

Extension is *.otif and works wherever *.tif files are supported. I guess it should be added as a supported format.

image format is “.otif” -> scanner i guess is from optra

Hi @andreped, I was testing the Python script to run FAST on a few images I found out that the results were slightly different. Investigating it further, something might be wrong with those images as the script works well with FAST’s test data.

Thanks a lot, it worked.

Hi again @lomshabhishek

Sorry for not spotting this error as well. When you do patch-wise classification the output of the patch stitcher is a Tensor, not an Image. A Tensor can not be saved directly as a TIFF at the momemt, thus you have to use HDF5TensorExporter instead to export it to a HDF5 file. The TIFFImagePyramidExporter should have produced an error message stating this, not a seg fault…

Also you don’t need to use RunUntilFinished when you export after a window like this. If you remove the window you should use RunUntilFinished.

# Export at the end (patch-wise classification becomes a Tensor, not an image)
fast.HDF5TensorExporter.create(f'{image_name}_processed.hd5')\
    .connect(stitcher).run()

fast.TIFFImagePyramidExporter.create(f'{image_name}_heatmap.tiff')\
    .connect(tissueSegmentation).run()

If you still want to save the Tensor as a TIFF image you can do that by first converting the tensor to an image using the TensorToImage object. This will give a float image, and since FAST currently can’t handle TIFF other than uint8, you can cast the float image to a uint8 image like so:

# Export at the end (patch-wise classification becomes a Tensor, not an image)
# Here we only convert channel 1 in the tensor to an image
channel = 1
tensor2image = fast.TensorToImage.create([channel]).connect(stitcher)
# Convert image to uint8, and multiply every pixel by 255, as they are in the float range 0-1.
caster = fast.ImageCaster.create(fast.TYPE_UINT8, 255.).connect(tensor2image) 
fast.TIFFImagePyramidExporter.create(f'{image_name}_processed_channel_{channel}.tiff')\
    .connect(caster).run()

fast.TIFFImagePyramidExporter.create(f'{image_name}_heatmap.tiff')\
    .connect(tissueSegmentation).run()

You can also use TensorToSegmentation instead of TensorToImage and ImageCaster if you want a binary output.