View Issue Details

IDProjectCategoryView StatusLast Update
0003382Slicer4Core: CLI infrastructurepublic2015-09-09 08:29
Reporterfedorov Assigned Tomillerjv  
PrioritynormalSeveritycrashReproducibilityalways
Status closedResolutionfixed 
Product Version 
Target VersionSlicer 4.5.0-1Fixed in VersionSlicer 4.5.0-1 
Summary0003382: Crash while attempting to read a MultiVolume node produced by a CLI
Description

Reproducible with the PkModeling extension at this branch:

https://github.com/fedorov/PkModeling/tree/save-concentrations-and-fit

Crash messages:

ModuleType: SharedObjectModule
PkModeling command line:

slicer:0x11d736b30 --processinformationaddress 0x7fb1929d9e90 --T1Blood 1600 --T1Tissue 1597 --relaxivity 0.0039 --S0grad 15.0 --fTolerance 1e-4 --gTolerance 1e-4 --xTolerance 1e-5 --epsilon 1e-9 --maxIter 200 --hematocrit 0.4 --aucTimeInterval 90 --roiMask slicer:0x7fb191435ce0#vtkMRMLScalarVolumeNode2 --prescribedAIF /var/folders/sl/6ssprw115g3bkfgm9cyzg0940000gn/T/Slicer/CEDEG_vtkMRMLDoubleArrayNodeB.mcsv --outputKtrans slicer:0x7fb191435ce0#vtkMRMLScalarVolumeNode3 --outputVe slicer:0x7fb191435ce0#vtkMRMLScalarVolumeNode4 --outputRSquared slicer:0x7fb191435ce0#vtkMRMLScalarVolumeNode5 --concentrations /var/folders/sl/6ssprw115g3bkfgm9cyzg0940000gn/T/Slicer/CEDEG_vtkMRMLMultiVolumeNodeD.nrrd --fitted /var/folders/sl/6ssprw115g3bkfgm9cyzg0940000gn/T/Slicer/CEDEG_vtkMRMLMultiVolumeNodeE.nrrd /var/folders/sl/6ssprw115g3bkfgm9cyzg0940000gn/T/Slicer/CEDEG_vtkMRMLMultiVolumeNodeB.nrrd

PkModeling standard output:

ctest needs: CTEST_FULL_OUTPUT
Timing: 0, 63.2324, 83.4766, 103.717, 123.961, 144.203, 164.447, 184.689, 204.932, 225.176, 245.42, 265.662, 285.904, 306.148, 326.391, 346.631, 366.875, 387.119, 407.361, 427.604, 447.848, 468.09, 488.332, 508.578, 528.82, 549.062, 569.305, 589.547,
Model type: 1

ERROR: In /Users/fedorov/github/Slicer/Libs/vtkITK/vtkITKArchetypeImageSeriesScalarReader.cxx, line 160
vtkITKArchetypeImageSeriesScalarReader (0x7fb1992cbff0): UpdateFromFile: Unsupported number of components (only 1 allowed): 28

ERROR: In /Users/fedorov/github/Slicer/Libs/MRML/Core/vtkMRMLVolumeArchetypeStorageNode.cxx, line 398
vtkMRMLVolumeArchetypeStorageNode (0x7fb198c97d40): ReadData: Not a scalar volume file: /var/folders/sl/6ssprw115g3bkfgm9cyzg0940000gn/T/Slicer/CEDEG_vtkMRMLMultiVolumeNodeD.nrrd

ERROR: In /Users/fedorov/github/Slicer/Libs/vtkITK/vtkITKArchetypeImageSeriesScalarReader.cxx, line 160
vtkITKArchetypeImageSeriesScalarReader (0x7fb194e7f450): UpdateFromFile: Unsupported number of components (only 1 allowed): 28

ERROR: In /Users/fedorov/github/Slicer/Libs/MRML/Core/vtkMRMLVolumeArchetypeStorageNode.cxx, line 398
vtkMRMLVolumeArchetypeStorageNode (0x7fb194e797e0): ReadData: Not a scalar volume file: /var/folders/sl/6ssprw115g3bkfgm9cyzg0940000gn/T/Slicer/CEDEG_vtkMRMLMultiVolumeNodeE.nrrd

error: [/Users/fedorov/local/builds/Slicer4-Release/Slicer-build/bin/Slicer.app/Contents/MacOS/./Slicer] exit abnormally - Report the problem.

TagsNo tags attached.

Activities

millerjv

millerjv

2013-09-09 09:48

developer   ~0009903

I see what is happening.

The outputs of a CLI are ultimately read into Slicer using the vtkSlicerApplicationLogic::ProcessReadNodeData() method.

If there is a StorageNode attached to the node, then that is what is used to read in the data. If there not a StorageNode attached to the node, then the method tries to create one.

The create logic is hardcoded for the volume node types in the Slicer trunk. Since many of the volume node types are specializations of other volume node types, there is a precedence in the search for a compatible storage node type.

Unfortunately, MultiVolume is not in the Slicer trunk, so a case cannot be hard coded for it.

But I recall adding something to MRML a while back so that you could ask a node to create a storage node of the appropriate type. Perhaps a block of code with this hard coded specialization can be replaced with that.

millerjv

millerjv

2013-09-09 10:07

developer   ~0009905

Try this change

diff --git a/Base/Logic/vtkSlicerApplicationLogic.cxx b/Base/Logic/vtkSlicerAppl
index 41e7412..1351c62 100644
--- a/Base/Logic/vtkSlicerApplicationLogic.cxx
+++ b/Base/Logic/vtkSlicerApplicationLogic.cxx
@@ -917,12 +917,7 @@ void vtkSlicerApplicationLogic::ProcessReadNodeData(ReadDat
{
// Load a scalar or vector volume node
//

  • // Need to maintain the original coordinate frame established by
  • // the images sent to the execution model
  • vtkMRMLVolumeArchetypeStorageNode *vin
  • = vtkMRMLVolumeArchetypeStorageNode::New();
  • vin->SetCenterImage(0);
  • storageNode = vin;
  • storageNode = storableNode->CreateDefaultStorageNode();
    }
    else if (dtvnd || dwvnd)
    {
fedorov

fedorov

2013-09-09 10:29

developer   ~0009908

The node is read correctly as multivolume, but the display node is incorrectly set to ScalarVolumeDisplayNode.

millerjv

millerjv

2013-09-09 10:52

developer   ~0009910

Okay. This next one it trickier.

Add a method CreateDefaultDisplayNodes() in MRMLMultiVolumeNode. See the MRMLFiberBundleNode for a reference. The method is defined in MRMLDisplayableNode.

Then apply this diff (assuming the previous diff was applied).

diff --git a/Base/Logic/vtkSlicerApplicationLogic.cxx b/Base/Logic/vtkSlicerAppl
index 41e7412..7030624 100644
--- a/Base/Logic/vtkSlicerApplicationLogic.cxx
+++ b/Base/Logic/vtkSlicerApplicationLogic.cxx
@@ -1112,6 +1107,12 @@ void vtkSlicerApplicationLogic::ProcessReadNodeData(ReadD
// Get the right type of display node. Only create a display node
// if one does not exist already
//

  • vtkMRMLDisplayableNode *displayableNode = vtkMRMLDisplayableNode::SafeDownCas
  • if (displayableNode)
  • {
  • displayableNode->CreateDefaultDisplayNodes();
  • if (!displayabeNode->GetDisplayNode())
  • {
    if ((svnd && !svnd->GetDisplayNode())
    || (vvnd && !vvnd->GetDisplayNode()))
    {
    @@ -1139,11 +1140,11 @@ void vtkSlicerApplicationLogic::ProcessReadNodeData(Read
    if (dtvnd)
    {
    vtkMRMLDiffusionTensorVolumeDisplayNode *dtvdn = vtkMRMLDiffusionTensorVo
    -// dtvdn->SetWindow(0);
    -// dtvdn->SetLevel(0);
    -// dtvdn->SetUpperThreshold(0);
    -// dtvdn->SetLowerThreshold(0);
    -// dtvdn->SetAutoWindowLevel(1);
  • // dtvdn->SetWindow(0);
  • // dtvdn->SetLevel(0);
  • // dtvdn->SetUpperThreshold(0);
  • // dtvdn->SetLowerThreshold(0);
  • // dtvdn->SetAutoWindowLevel(1);
    disp = dtvdn; // assign to superclass pointer
    }
    else
    @@ -1237,6 +1238,8 @@ void vtkSlicerApplicationLogic::ProcessReadNodeData(ReadDa
    }
    disp->Delete();
    }
  • }
  • }
millerjv

millerjv

2013-09-09 10:55

developer   ~0009911

This is hack but it may work. Basically, the CreateDefaultDisplayNodes() does what we want but it didn't exist when we wrote ProcessReadNodeData() method. Unfortunately, CreateDefaultDisplayNodes() has not been propagated through the node types.

Ideally, we should be able to call

sn = storableNode->CreateDefaultStorageNode();
displayableNode->CreateDefaultDisplayNodes();

and eliminate almost all the code in ProcessReadNodeData().

fedorov

fedorov

2013-09-09 13:17

developer   ~0009913

Jim can you clarify;

1) CreateDefaultDisplayNodes() is defined on the MRMLNode, not on MRMLDisplayableNode - is this correct? ==>

  • vtkMRMLDisplayableNode *displayableNode = vtkMRMLDisplayableNode::SafeDownCas
  • if (displayableNode)
  • {
  • displayableNode->CreateDefaultDisplayNodes();

2) long lines in your patch are incomplete

millerjv

millerjv

2013-09-09 13:25

developer   ~0009914

1) CreateDefaultDisplayNodes() is defined on MRMLDisplayableNode NOT on MRMLNode. So you have to cast the node to a MRMLDisplayableNode before you can call it.

2) Sorry about the truncation in the patch. Here is a better one

diff --git a/Base/Logic/vtkSlicerApplicationLogic.cxx b/Base/Logic/vtkSlicerApplicationLogic.cxx
index 41e7412..96ac498 100644
--- a/Base/Logic/vtkSlicerApplicationLogic.cxx
+++ b/Base/Logic/vtkSlicerApplicationLogic.cxx
@@ -1112,6 +1107,12 @@ void vtkSlicerApplicationLogic::ProcessReadNodeData(ReadDataRequest& req)
// Get the right type of display node. Only create a display node
// if one does not exist already
//

  • vtkMRMLDisplayableNode *displayableNode = vtkMRMLDisplayableNode::SafeDownCast(nd);
  • if (displayableNode)
  • {
  • displayableNode->CreateDefaultDisplayNodes();
  • if (!displayableNode->GetDisplayNode())
  • {
    if ((svnd && !svnd->GetDisplayNode())
    || (vvnd && !vvnd->GetDisplayNode()))
    {
    @@ -1139,11 +1140,11 @@ void vtkSlicerApplicationLogic::ProcessReadNodeData(ReadDataRequest& req)
    if (dtvnd)
    {
    vtkMRMLDiffusionTensorVolumeDisplayNode *dtvdn = vtkMRMLDiffusionTensorVolumeDisplayNode::New();
    -// dtvdn->SetWindow(0);
    -// dtvdn->SetLevel(0);
    -// dtvdn->SetUpperThreshold(0);
    -// dtvdn->SetLowerThreshold(0);
    -// dtvdn->SetAutoWindowLevel(1);
  • // dtvdn->SetWindow(0);
  • // dtvdn->SetLevel(0);
  • // dtvdn->SetUpperThreshold(0);
  • // dtvdn->SetLowerThreshold(0);
  • // dtvdn->SetAutoWindowLevel(1);
    disp = dtvdn; // assign to superclass pointer
    }
    else
    @@ -1237,6 +1238,8 @@ void vtkSlicerApplicationLogic::ProcessReadNodeData(ReadDataRequest& req)
    }
    disp->Delete();
    }
  • }
  • }

    // Cause the any observers to fire (we may have avoided calling
    // modified on the node)

millerjv

millerjv

2013-09-09 13:27

developer   ~0009915

Here is a patch ignoring space changes

diff --git a/Base/Logic/vtkSlicerApplicationLogic.cxx b/Base/Logic/vtkSlicerApplicationLogic.cxx
index 41e7412..96ac498 100644
--- a/Base/Logic/vtkSlicerApplicationLogic.cxx
+++ b/Base/Logic/vtkSlicerApplicationLogic.cxx
@@ -1112,6 +1107,12 @@ void vtkSlicerApplicationLogic::ProcessReadNodeData(ReadDataRequest& req)
// Get the right type of display node. Only create a display node
// if one does not exist already
//

  • vtkMRMLDisplayableNode *displayableNode = vtkMRMLDisplayableNode::SafeDownCast(nd);
  • if (displayableNode)
  • {
  • displayableNode->CreateDefaultDisplayNodes();
  • if (!displayableNode->GetDisplayNode())
  • {
    if ((svnd && !svnd->GetDisplayNode())
    || (vvnd && !vvnd->GetDisplayNode()))
    {
    @@ -1237,6 +1238,8 @@ void vtkSlicerApplicationLogic::ProcessReadNodeData(ReadDataRequest& req)
    }
    disp->Delete();
    }
  • }
  • }

    // Cause the any observers to fire (we may have avoided calling
    // modified on the node)

fedorov

fedorov

2013-09-09 13:28

developer   ~0009916

1) CreateDefaultDisplayNodes() is defined on MRMLDisplayableNode
NOT on MRMLNode. So you have to cast the node to a MRMLDisplayableNode
before you can call it.

Sorry about that, you had "DisplayableNode", but I was thinking "DisplayNode" ...

Thank you for the corrections.

fedorov

fedorov

2013-09-09 14:29

developer   ~0009917

This seems to work. Should I submit a pull request to Slicer trunk when done or will you integrate?

Will update MultiVolume MRML in the external module too.

We should probably coordinate with JC to have this backported to 4.3 - do you foresee any issue with that?

fedorov

fedorov

2013-09-09 14:49

developer   ~0009918

Fixes to MultiVolume MRML: https://github.com/fedorov/MultiVolumeExplorer/commit/ab7eb9411c5eaacacf81685b4c7e05cf1935d9a3

Corresponding update in Slicer r22420 (todo ask JC to backport).

Patched Slicer branch: https://github.com/fedorov/Slicer/tree/3382-fix-loading-multivolumes-from-CLIs

millerjv

millerjv

2013-09-09 14:54

developer   ~0009919

The issue is that the above is kind of a hack. I could see someone editting it out because it is not clear why it is needed.

For maintainability, I would prefer that fix the ProcessReadNodeData() method to transition all the special case code to method calls in the underlying nodes (e.g. CreateDefaultStorageNode(), CreateDefaultDisplayNodes(), whatever else we need). It is a pretty big change. Really should change all the DisplayableNodes to have a CreateDefaultDisplayNodes method. That would need a good bit of testing. Plus it looks like the Freesurfer path is little more complicated. Not sure I am comfortable doing it in a rush to backport to 4.3 in the next few days.

fedorov

fedorov

2013-09-09 15:02

developer   ~0009920

Sounds good. We should decide what to do with PkModeling. I think the recent patches add important functionality, but not sure they should be included in the 4.3 release of the extension if we know that running it from the GUI will crash Slicer.

millerjv

millerjv

2013-09-23 11:52

developer   ~0010065

Working on a new version of PrcessReadNodeData().

Patch will either

  1. Rely on a node having CreateDefaultDisplayNode() and CreateDefaultStorageNode() methods, or

  2. Use a factory to create nodes like in vtkSlicerVolumesLogic.

fedorov

fedorov

2014-02-04 08:38

developer   ~0010556

Reminder sent to: millerjv

Jim, do you have an estimate when this crash will be fixed?

millerjv

millerjv

2014-02-04 08:49

developer   ~0010557

Thanks for the reminder. I had completely forgotten about it. I'll take some time to study it again and see if I still like the solution I had planned.

fedorov

fedorov

2014-02-04 12:14

developer   ~0010560

Thank you Jim. If there is something I can help with, let me know.

pieper

pieper

2014-03-06 09:39

administrator   ~0011244

Shall we target the 4.4 release for this?

fedorov

fedorov

2014-03-26 08:21

developer   ~0011464

Jim, any updates? Do you think this will be fixed for 4.4?

millerjv

millerjv

2014-04-24 09:59

developer   ~0011663

Last edited: 2014-04-24 10:00

Target 4.4

fedorov

fedorov

2015-01-07 11:50

developer   ~0012853

Jim says, we should try to apply the patch he suggested early in the history of this bug. I will try that and report if this fixes the problem.

fedorov

fedorov

2015-01-08 12:24

developer   ~0012863

Patch integrated with today's master, and is available in the pull request here: https://github.com/Slicer/Slicer/pull/225

Jim confirmed he is going to review and add comments before merging.

fedorov

fedorov

2015-01-12 12:18

developer   ~0012882

Merged with master in 23876 and 23877.

Issue History

Date Modified Username Field Change
2013-09-09 09:07 fedorov New Issue
2013-09-09 09:07 fedorov Status new => assigned
2013-09-09 09:07 fedorov Assigned To => millerjv
2013-09-09 09:48 millerjv Note Added: 0009903
2013-09-09 10:07 millerjv Note Added: 0009905
2013-09-09 10:29 fedorov Note Added: 0009908
2013-09-09 10:52 millerjv Note Added: 0009910
2013-09-09 10:55 millerjv Note Added: 0009911
2013-09-09 13:17 fedorov Note Added: 0009913
2013-09-09 13:25 millerjv Note Added: 0009914
2013-09-09 13:27 millerjv Note Added: 0009915
2013-09-09 13:28 fedorov Note Added: 0009916
2013-09-09 14:29 fedorov Note Added: 0009917
2013-09-09 14:49 fedorov Note Added: 0009918
2013-09-09 14:54 millerjv Note Added: 0009919
2013-09-09 15:02 fedorov Note Added: 0009920
2013-09-23 11:52 millerjv Note Added: 0010065
2013-10-01 12:16 jcfr Target Version => Slicer 4.3.1
2013-10-01 12:17 jcfr Target Version Slicer 4.3.1 => Slicer 4.3.2
2014-02-04 08:38 fedorov Note Added: 0010556
2014-02-04 08:49 millerjv Note Added: 0010557
2014-02-04 12:14 fedorov Note Added: 0010560
2014-03-06 09:39 pieper Note Added: 0011244
2014-03-06 10:15 nicole Target Version Slicer 4.3.2 => Slicer 4.4.0
2014-03-26 08:21 fedorov Note Added: 0011464
2014-04-24 09:59 millerjv Note Added: 0011663
2014-04-24 10:00 millerjv Note Edited: 0011663
2014-09-25 12:49 jcfr Target Version Slicer 4.4.0 => Slicer 4.4.1
2015-01-07 11:50 fedorov Note Added: 0012853
2015-01-07 11:50 fedorov Assigned To millerjv => fedorov
2015-01-08 12:23 fedorov Assigned To fedorov => millerjv
2015-01-08 12:24 fedorov Note Added: 0012863
2015-01-12 12:18 fedorov Note Added: 0012882
2015-01-13 03:13 fedorov Status assigned => closed
2015-01-13 03:13 fedorov Resolution open => fixed
2015-01-13 03:13 fedorov Fixed in Version => Slicer 4.4.1
2015-09-09 08:29 jcfr Fixed in Version Slicer 4.4.1 => Slicer 4.5.0-1
2015-09-09 08:29 jcfr Target Version Slicer 4.4.1 => Slicer 4.5.0-1