View Issue Details

IDProjectCategoryView StatusLast Update
0001783Slicer4Core: MRMLpublic2014-03-06 06:10
Reporternicole Assigned Tonicole  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version 
Target VersionSlicer 4.1.0Fixed in VersionSlicer 4.1.1 
Summary0001783: Losing model hierarchy display nodes on scene save
Description

I think that the cleaning up of unreferenced nodes is deleting the display node that the model hierarchy node points to. The model hierarchy node doesn't inherit from displayable nodes, so it's using vtkMRMLDisplayableHierarchyNode's manual managment of display node id, but I suspect it's not using the correct set reference macro.

Steps To Reproduce

Load a model
In the models module, right click and add a hierarchy.
Drag the model into the hierarchy.
File->Save

DisplayableHierarchyNode::UpdateReferences can't find the display node and sets the display node id to null, if you try to get the display node id for the model heirarchy node now, it will be empty.

Additional Information

In python:
h1 = slicer.mrmlScene.GetNodeByID("vtkMRMLModelHierarchyNode1")
h1.GetDisplayNodeID()

In some cases the saved mrml file will have a scene view that has the correct display node id, so restoring the scene view from the save point will lead to a valid display node on the hierarchy node. But just loading the mrml scene will usually result in missing display nodes.

TagsNo tags attached.

Activities

nicole

nicole

2012-03-03 12:43

administrator   ~0003769

Can also cause a crash on scene close when saved a scene with fiducials in it, as the annotation hierarchy node lost its display node on scene save.

nicole

nicole

2012-03-05 08:31

administrator   ~0003783

Looks like the culprit is in the save data dialog when it calls:
// remove unreferenced nodes
vtkMRMLLogic *mrmlLogic = vtkMRMLLogic::New();
mrmlLogic->SetScene(this->MRMLScene);
mrmlLogic->RemoveUnreferencedDisplayNodes();
mrmlLogic->RemoveUnreferencedStorageNodes();
mrmlLogic->Delete();

In RemoveUnreferencedDisplayNodes, it goes through the displayable nodes and makes sure each display node is pointed to by something. The problem is that the hierarchy nodes aren't displayable nodes, so their display nodes get removed.
The call to RemoveUnreferencedDisplayNodes was added in svn 15936 in Jan 2011, before I added the saving of a default scene view on mrml scene save.
Something else in the scene node accounting must have changed to cause this crash on scene close (the qt scene model hits an assert that a node was removed without a notification).
When I remove this logic call, the display node doesn't disappear, but I still get the "node removed without notification crash" on scene close. That call is only used in the save data dialog, so there's something else clearing out display nodes that aren't pointed to by displayable nodes (it may be that the wrong Reference macro is used so that the mrml scene doesn't have it properly recorded in the list of referenced nodes).

Alex: what's the best vtkMRMLScene method to call to trigger a clean up of unreferenced nodes after saving a mrml scene?

nicole

nicole

2012-03-05 09:09

administrator   ~0003784

More digging: if I keep the mrmlLogic calls out, creating a model hierarchy and then saving it, the hierarchy display node is fine in the scene references:
h1 = slicer.mrmlScene.GetNodeByID("vtkMRMLModelHierarchyNode1")
m = slicer.mrmlScene.GetNodeByID("vtkMRMLModelNode5")
col = slicer.mrmlScene.GetReferencedNodes(h1)
col.GetItemAsObject(1).GetID()
returns model display node 6 (0 returns itself)
And if check the model node after save:
col = slicer.mrmlScene.GetReferencedNodes(m)

col.GetItemAsObject(0).GetID()
'vtkMRMLModelNode5'
col.GetItemAsObject(1).GetID()
'vtkMRMLModelStorageNode1'
col.GetItemAsObject(2).GetID()
'vtkMRMLModelDisplayNode5'
t = slicer.mrmlScene.GetNodeByID("vtkMRMLModelDisplayNode5")
t.GetID()
'vtkMRMLModelDisplayNode5'

but when close the scene, it crashes with this error:
ERROR: In /projects/birn/nicole/Slicer4/Slicer4/Libs/MRML/Core/vtkMRMLScene.cxx, line 1356
vtkMRMLScene (0x1510680): RemoveNode: Node vtkMRMLModelDisplayNode/ModelDisplay_4[0x7159fc0] already removed

ERROR: In /projects/birn/nicole/Slicer4/Slicer4/Libs/MRML/Core/vtkMRMLScene.cxx, line 1364
vtkMRMLScene (0x1510680): RemoveNode: class: vtkMRMLModelDisplayNode name:ModelDisplay_4 id: vtkMRMLModelDisplayNode5[0x7159fc0] can't be found by ID

ASSERT failure in qMRMLSceneModel::onMRMLSceneNodeAboutToBeRemoved(): "A node has been removed from the scene but the scene model has never been notified it has been added in the first place. Maybe vtkMRMLScene::AddNodeNoNotify() has been used instead of vtkMRMLScene::AddNode", file /projects/birn/nicole/Slicer4/Slicer4/Libs/MRML/Widgets/qMRMLSceneModel.cxx, line 1131

Is something in the scene close removing nodes in the wrong order?

nicole

nicole

2012-03-05 09:50

administrator   ~0003785

It could be that something's watching for node removed events and removing related nodes before the scene RemoveAllNodesExceptSingletons gets to them in it's loop. Putting
this->Start/EndState(vtkMRMLScene::BatchProcessState);
around the loop didn't help. But in vtkSlicerModelsLogic.cxx if I turned off AutoRemoveDisplayAndStorageNodes, no crash on scene close. That method doesn't currently check for scene state, is adding a check there for the mrml scene being in a close scene state enough?

nicole

nicole

2012-03-05 10:02

administrator   ~0003786

Did a quick test of checking for scene IsClosing, no crash.

The combo of two methods trying to clean up the scene caused two interelated crashes, my recommendation is:

  • take out the clean up from the save dialog
  • add checks for IsClosing and/or BatchProcessing in modules that implement OnMRMLSceneNodeRemoved
  • make sure that modules that add extra nodes when nodes are added clean up after themselves when those nodes are removed
nicole

nicole

2012-03-06 06:10

administrator   ~0003791

svn 19519 adds a check for IsClosign to the models OnMRMLSceneNodeRemoved

nicole

nicole

2012-03-06 11:05

administrator   ~0003796

svn 19525 removes the clearing out of display and storage nodes on scene save, need to make the modules respond to node removed events to clear out "extra" nodes that they've added (display, storage) for the nodes they manage.

Issue History

Date Modified Username Field Change
2012-03-03 12:23 nicole New Issue
2012-03-03 12:23 nicole Status new => assigned
2012-03-03 12:23 nicole Assigned To => alexy
2012-03-03 12:43 nicole Note Added: 0003769
2012-03-05 08:31 nicole Note Added: 0003783
2012-03-05 09:09 nicole Note Added: 0003784
2012-03-05 09:50 nicole Note Added: 0003785
2012-03-05 10:02 nicole Note Added: 0003786
2012-03-06 06:10 nicole Note Added: 0003791
2012-03-06 11:05 nicole Note Added: 0003796
2012-03-06 11:05 nicole Assigned To alexy => nicole
2012-03-06 11:05 nicole Status assigned => resolved
2012-03-06 11:05 nicole Resolution open => fixed
2012-05-03 07:04 nicole Status resolved => closed
2014-03-06 06:10 jcfr Fixed in Version => Slicer 4.1.1