View Issue Details

IDProjectCategoryView StatusLast Update
0004416Slicer4Core: Diffusion and Tractography (Any modules)public2018-10-03 13:40
ReporterlassoanAssigned Toinorton 
PrioritynormalSeveritycrashReproducibilityalways
Status assignedResolutionopen 
Product VersionSlicer 4.7.0 
Target VersionSlicer 4.11.0Fixed in Version 
Summary0004416: Crash when displaying DTI volume in slice view
Description

When a DTI volume is shown in a slice view, then Slicer crashes as soon as the rendering pipeline is updated.

The crash occurs in vtkImageReslice:

    vtkImaging-7.1.dll!`anonymous namespace'::vtkInterpolateRound<double>(double val, double & rnd)  Line 1293 + 0xb bytes   C++
>   vtkImaging-7.1.dll!`anonymous namespace'::vtkImageResliceConversion<double,double>::Convert(void * & outPtr0, const double * inPtr, int numscalars, int n)  Line 1417    C++
    vtkImaging-7.1.dll!`anonymous namespace'::vtkReslicePermuteExecute<double>(vtkImageReslice * self, vtkDataArray * scalars, vtkAbstractImageInterpolator * interpolator, vtkImageData * outData, void * outPtr, double scalarShift, double scalarScale, void (void *, void *, int, int, int, int, int, int, int)* convertScalars, int * outExt, int threadId, double [4]* matrix)  Line 3017  C++
    vtkImaging-7.1.dll!vtkImageReslice::ThreadedRequestData(vtkInformation * __formal, vtkInformation * __formal, vtkInformation * __formal, vtkImageData * * * inData, vtkImageData * * outData, int * outExt, int threadId)  Line 3281    C++
    vtkCommon-7.1.dll!vtkThreadedImageAlgorithmThreadedExecute(void * arg)  Line 443    C++
    kernel32.dll!BaseThreadInitThunk()  + 0x14 bytes    
    ntdll.dll!RtlUserThreadStart()  + 0x21 bytes    

Maybe DTI volumes shouldn't be selected as volumes in the slice viewer? And/or vtkImageReslice should be fixed to not crash.

I've come across this issue when I tried to test this PR: https://github.com/Slicer/Slicer/pull/776.

Steps To Reproduce

When this script into the Python console, Slicer crashes:

# Load volume
import SampleData
logic = SampleData.SampleDataLogic()
vol = logic.downloadFromSource(SampleData.SampleDataSource('dt-helix-ref-BS', 'https://github.com/Slicer/Slicer/raw/master/Modules/CLI/ResampleDTIVolume/Data/Baseline/dt-helix-ref-BS.nrrd', 'dt-helix-ref-BS.nrrd', 'dt-helix-ref-BS.nrrd'))[0]

# Force rendering pipeline update
vol.GetImageData().Modified()
slicer.app.layoutManager().sliceWidget('Red').sliceView().renderWindow().GetRenderers().GetItemAsObject(0).Render()
TagsNo tags attached.

Activities

lassoan

lassoan

2017-08-16 18:53

developer   ~0015053

The issue is not in the NRRD reader, as a .mha version of the file (attached) crashes the same way.
However, there is no crash when the volume is loaded directly using a VTK reader, only when loaded into a volume node.

Crash:

[success,vol]=slicer.util.loadVolume(r'c:\D\S4\Modules\CLI\ResampleDTIVolume\Data\Baseline\dt-helix-ref-BS.mha', returnNode=True)
reslice = vtk.vtkImageReslice()
reslice.SetInputData(vol.GetImageData())
reslice.Update()

No crash:

reader=vtk.vtkMetaImageReader()
reader.SetFileName(r'c:\D\S4\Modules\CLI\ResampleDTIVolume\Data\Baseline\dt-helix-ref-BS.mha')
reader.Update()
reslice = vtk.vtkImageReslice()
reslice.SetInputData(reader.GetOutput())
reslice.Update()
lassoan

lassoan

2017-08-16 18:54

developer  

dt-helix-ref-BS.mha (711,933 bytes)
inorton

inorton

2017-12-30 22:57

developer   ~0015472

Last edited: 2017-12-30 23:18

View 2 revisions

backtrace for crash in https://issues.slicer.org/view.php?id=4416#c15053

    frame #0: 0x0000000119dd9d02 libvtkImaging-7.1.1.dylib`void (anonymous namespace)::vtkReslicePermuteExecute<double>(self=0x000000014364a120, scalars=0x0000000000000000, interpolator=0x0000000144fc7c30, outData=0x0000000144fb2a00, outPtr=0x0000000127f1cf20, scalarShift=0, scalarScale=1, convertScalars=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00, outExt=0x000070000f4b7eb0, threadId=1, matrix=0x000070000f4b7d20)(void*, void*, int, int, int, int, int, int, int), int*, int, double (*) [4]) at vtkImageReslice.cxx:2837
   2834
   2835   // if doConversion is false, a special fast-path will be used
   2836   bool doConversion = true;
-> 2837   int inputScalarType = scalars->GetDataType();
   2838   if (interpolationMode == VTK_NEAREST_INTERPOLATION &&
   2839       inputScalarType == scalarType && !convertScalars && !rescaleScalars &&
   2840       nsamples == 1)
inorton

inorton

2017-12-30 23:06

developer   ~0015473

In the backtrace above, scalars is passed down null, soscalars->GetDataType() segfaults. I don't know if that is considered a bug in vtkImageReslice, but I think the assumption that the image has scalars attached is pervasive...

The origin of the crash is the lack of scalars attached to the vtkImageData by the reader, because the imagedata is storing tensors instead.

In interactive use, this works out fine (we use the DT slice view feature very often), because scalars are assigned by the tensor -> scalar filter pipeline in vtkMRMLDiffusionTensorVolumeSliceDisplayNode. I guess the crash happens when Modified() is called directly because the pipeline has not been updated.

lassoan

lassoan

2017-12-31 01:28

developer   ~0015474

It is definitely a bug in vtkImageReslice. It should be checked that "scalars" is non-null before it is used. It is done like that it many other filters where GetDataType() is used.

@inorton, could you add a null-pointer check into vtkImageReslice and submit a pull request to VTK? If not, then we may ask David Gobbi (author of this class) to get this fixed.

jcfr

jcfr

2018-03-22 02:50

administrator   ~0015600

I was able to reproduce this in Slicer r27094

In vtkImageReslice::ThreadedRequestData, I tried adding the following without success:

  [...]
  // Get the input scalars
  if (inData[0][0] == nullptr ||
      inData[0][0]->GetPointData() == nullptr ||
      inData[0][0]->GetPointData()->GetScalars() == nullptr)
  {
    return;
  }
  vtkDataArray *scalars = inData[0][0]->GetPointData()->GetScalars();
  if (scalars == nullptr)
  {
    return;
  }
 [...]
pieper

pieper

2018-09-27 10:41

administrator   ~0016046

This doesn't happen with the dti sample data. Does it happen in practice with real data or only with the synthetic helix dataset?

lassoan

lassoan

2018-09-27 16:43

developer   ~0016047

It crashes the same way with the DTI sample data (DTIVolume.nhdr+raw):

# Load volume
import SampleData
logic = SampleData.SampleDataLogic()
vol = logic.downloadDTIBrain()

# Force rendering pipeline update
vol.GetImageData().Modified()
slicer.app.layoutManager().sliceWidget('Red').sliceView().renderWindow().GetRenderers().GetItemAsObject(0).Render()

You can also trigger the crash by just calling Modified() on the image then interacting with a slice viewer:

# Load volume
import SampleData
logic = SampleData.SampleDataLogic()
vol = logic.downloadDTIBrain()

# Force rendering pipeline update
vol.GetImageData().Modified()

# now add markup in a slice view => it will crash
lassoan

lassoan

2018-09-27 16:45

developer   ~0016048

When I removed this hack (https://github.com/Slicer/Slicer/blob/f553c8c881c0438b0c6c229d713d430a4c95e7b0/Libs/MRML/Logic/vtkMRMLSliceLayerLogic.cxx#L678-L684) then Slicer crashed in a very similar way (there seems to be a mismatch between the expected and actual scalar type: double/float), so maybe the issue is that this workaround is not applied when calling Modified() on the input image data. The proper solution might be to fix this in VTK (but interestingly, the bug is supposed to be fixed already - see https://www.paraview.org/Bug/print_bug_page.php?bug_id=14692).

lassoan

lassoan

2018-09-28 18:39

developer   ~0016049

Last edited: 2018-09-28 18:42

View 2 revisions

I discussed this with David Gobbi in email. vtkImageData does not support "new" (5-year-old) VTK pipeline. Imaging filters have just been upgraded to remain functional, but for example you cannot change the active scalar via pipeline (but it is hardcoded in vtkImageData object - for example vtkImageData:: GetScalarType() always uses the active scalar set in the data object and ignores information objects in the pipeline).

It would be significant effort to update the vtkImageData and all imaging filters to work properly with the new pipeline infrastructure. It would be a good time to work on this when we introduce image orientation to vtkImageData.

Until then, we must not use vtkAssignAttribute with vtkImageData. It is not supposed to work, and it does not work (with the current hack it sort of works, but a simple Modified() call on the image data crashes the application). We must only store a single point scalar array in vtkImageData (we can store tensor data in a 9-component float/double array, the same way as VTK nrrd reader does it).

@ihnorton Could you update DTI reader to store tensor data in a 9-component scalar in vtkImageData? This would allow simplification of the DTI image display pipeline: you could remove the two vtkAssignAttribute filters and remove the ugly hack.

jcfr

jcfr

2018-10-03 11:36

administrator   ~0016064

Following discussion during the last Slicer hangout, we are re-targeting this issue.

Issue History

Date Modified Username Field Change
2017-08-16 18:19 lassoan New Issue
2017-08-16 18:19 lassoan Status new => assigned
2017-08-16 18:19 lassoan Assigned To => inorton
2017-08-16 18:19 lassoan Description Updated View Revisions
2017-08-16 18:20 lassoan Description Updated View Revisions
2017-08-16 18:20 lassoan Steps to Reproduce Updated View Revisions
2017-08-16 18:53 lassoan Note Added: 0015053
2017-08-16 18:54 lassoan File Added: dt-helix-ref-BS.mha
2017-12-30 22:57 inorton Note Added: 0015472
2017-12-30 23:06 inorton Note Added: 0015473
2017-12-30 23:18 inorton Note Edited: 0015472 View Revisions
2017-12-31 01:28 lassoan Note Added: 0015474
2018-03-22 02:50 jcfr Note Added: 0015600
2018-09-27 10:41 pieper Note Added: 0016046
2018-09-27 16:43 lassoan Note Added: 0016047
2018-09-27 16:45 lassoan Note Added: 0016048
2018-09-28 18:39 lassoan Note Added: 0016049
2018-09-28 18:42 lassoan Note Edited: 0016049 View Revisions
2018-10-03 11:36 jcfr Note Added: 0016064
2018-10-03 13:40 jcfr Target Version Slicer 4.9.0 => Slicer 4.11.0