View Issue Details

IDProjectCategoryView StatusLast Update
0002727Slicer4Core: MRMLpublic2017-06-07 23:27
Reporterlassoan Assigned Toalexy  
PriorityurgentSeverityfeatureReproducibilityN/A
Status closedResolutionfixed 
Product Version 
Target VersionSlicer 4.3.0Fixed in VersionSlicer 4.4.0 
Summary0002727: Implementing node references is complex and error-prone
Description

Node referencing mechanism needs some design improvement, as for each referenced not in each node type about 10 methods shall be added/updated manually. This is very difficult to do, often done incorrectly (even in Slicer core code - see 0002725, 0002530). This is not a new problem, see http://massmail.spl.harvard.edu/public-archives/slicer-devel/2010/004874.html.

A potential solution would be to introduce a "ReferencedNodes" list, which would store pointer, ID string, node type name, and observers for each referenced node instead of adding separate member variables for these manually. This list could be fully maintained by the Copy, UpdateScene, UpdateReferenceID, UpdateReferences, ReadXMLAttributes, WriteXML, etc. methods implementation in vtkMRMLNode base class. Developers would just need to add an item to the ReferencedNodes list and all the rest would be handled by the MRML framework.

It would allow a very robust, simple, centralized implementation of all node reference updates for save/load, undo/redo, scene import features (which is not really feasible with the current implementation, where node reference handling is hand-crafted in each class).

Additional Information

Implemented new generic MRML node reference API in the vtkMRMLNode class. Implemented vtkMRMLDisplayableNode, vtkMRMLStorableNode, vtkMRMLTransformNode node using new API. Added tests to Libs/MRML/Core/Testing/vtkMRMLNodeTest1.cxx.

See link below for more details on the API:
http://wiki.slicer.org/slicerWiki/index.php?title=Documentation/Nightl/Developers/MRMLNodeReferences

At revision: 21810

TagsNo tags attached.

Activities

jcfr

jcfr

2012-11-05 11:04

administrator   ~0007053

Agreed. This is rather important especially considering extension development is used more and more. Having a simple and well tested API become more and more critical.

jcfr

jcfr

2013-03-19 10:43

administrator   ~0008153

@Andras: When you have a chance, check that it works for you and close the issue. Thanks.

jcfr

jcfr

2013-03-19 10:57

administrator   ~0008157

For reference: http://slicer-devel.65872.n3.nabble.com/mrml-references-redesign-tp4027889p4028039.html

pinter

pinter

2013-03-24 13:53

developer   ~0008225

The current version (file revision 21810) of vtkMRMLTransformableNode.h contains member variables with unprecedented type in VTK classes, such as

static const std::string TRANSFORM_NODE_REFERENCE_ROLE;
static const std::string TRANSFORM_NODE_REFERENCE_MRML_ATTRIBUTE_NAME;
and
std::string TransformNodeID;

This change caused some build errors in the SlicerRT extension, but more importantly it does not comply with the VTK convention, according to which these should be char* variables using vtkGet/Set macros.

lassoan

lassoan

2013-03-24 13:59

developer   ~0008226

Last edited: 2013-03-26 06:30

There is an issue with vtkMRMLNodeReference: it has public members variables, moreover these are non-wrappable (STL string).

EDIT (jc): VTK methods dealing with std::string can now be wrapped in VTK. See http://www.vtk.org/Wiki/VTK/Wrapper_Update_2010#Wrapping_vtkStdString

class VTK_MRML_EXPORT vtkMRMLNodeReference : public vtkObject
{
...
public:
std::string ReferenceRole;
std::string ReferencedNodeID;
...
};

To be conform with other parts of the Slicer core the obvious solution is to:

  • change std::string to char* (and update constructors, destructor, etc. accordingly)
  • move all private members and provide access through vtk Get/Set string macros
lassoan

lassoan

2013-03-24 14:05

developer   ~0008227

Another important modification needed:

Currently vtkMRMLNodeReference has a vtkObject parent, but vtkMRMLNodeReference also has a public constructor, destructor, copy constructor, and operator=.

Two possible solutions:

Option A: The vtkMRMLNodeReference class is converted to a simple struct that is only used privately inside vtkMRMLNode class.

Option B: The vtkMRMLNodeReference class is used publicly, but then it has to be converted to a proper VTK class (no public constructor, destructor, fully wrappable public interface, etc.).

alexy

alexy

2013-03-29 08:33

developer   ~0008263

converted vtkMRMLNodeReference class into a proper VTK class. Converted std::string's into char *. vtkMRMLNodeReference is now protected class inside vtkMRMLNode class.

http://viewvc.na-mic.org/viewvc.cgi/Slicer4?view=revision&revision=21850

finetjul

finetjul

2013-07-10 06:28

administrator   ~0008980

Right now, the reference role and reference mrml attribute name definitions seem a bit too verbose especially because there is no need to change the strings:
.h
char TransformNodeReferenceRole;
char
TransformNodeReferenceMRMLAttributeName;

vtkSetStringMacro(TransformNodeReferenceRole);
vtkGetStringMacro(TransformNodeReferenceRole);

vtkSetStringMacro(TransformNodeReferenceMRMLAttributeName);
vtkGetStringMacro(TransformNodeReferenceMRMLAttributeName);

.cxx
in constructor:
this->TransformNodeReferenceRole = 0;
this->TransformNodeReferenceMRMLAttributeName = 0;

this->SetTransformNodeReferenceRole("transform");
this->SetTransformNodeReferenceMRMLAttributeName("transformNodeRef");

this->AddNodeReferenceRole(this->GetTransformNodeReferenceRole(),
this->GetTransformNodeReferenceMRMLAttributeName());

I suggest the following instead:
.h
static char TransformNodeReferenceRole[];
static char TransformNodeReferenceMRMLAttributeName[];

vtkGetStringMacro(TransformNodeReferenceRole);
vtkGetStringMacro(TransformNodeReferenceMRMLAttributeName);

.cxx
char vtkMRMLSelectionNode::TransformNodeReferenceRole[] = "transform";
char vtkMRMLSelectionNode::TransformNodeReferenceMRMLAttributeName[] = "transformNodeRef";

in constructor:
this->AddNodeReferenceRole(this->GetTransformNodeReferenceRole(),
this->GetTransformNodeReferenceMRMLAttributeName());

Do you all approve that change ?

jcfr

jcfr

2013-07-10 06:33

administrator   ~0008981

Make sense. That would simplify the API.

lassoan

lassoan

2013-07-10 07:56

developer   ~0008982

I agree. Would be somewhat nicer with const.

If the role or attribute name does not have to be accessed from other classes (it shouldn't), then I would simply do:

.h
(nothing)

.cxx

static const char TRANSFORM_NODE_REFERENCE_ROLE[] = "transform";
static const char TRANSFORM_NODE_REFERENCE_MRML_ATTRIBUTE_NAME[] = "transformNodeRef";

in constructor:
this->AddNodeReferenceRole(TRANSFORM_NODE_REFERENCE_ROLE,
TRANSFORM_NODE_REFERENCE_MRML_ATTRIBUTE_NAME);

finetjul

finetjul

2013-07-10 08:07

administrator   ~0008983

Const is not possible when using vtkGetStringMacro(), it expects a char not const char :-(

Concerning the access from other classes, it should actually be possible to access those strings from subclasses I believe.

lassoan

lassoan

2013-07-10 08:23

developer   ~0008984

OK, keep it as a member variable then.

The non-const vtkGetStringMacro is unfortunate. We could add a simple get function with a const return value, but it would require a few extra lines of code, so not a perfect solution either.

jcfr

jcfr

2014-03-06 05:18

administrator   ~0011107

Closing resolved issues that have not been updated in more than 3 months

Related Changesets

Slicer: 2145-support-for-installing-extension-from-file 1c0a42cd

2013-07-15 11:23:48

finetjul

Details Diff
STYLE: Use static member variables for reference roles and attribute name

Issue 0002727

git-svn-id: http://svn.slicer.org/Slicer4/trunk@22186 3bd1e089-480b-0410-8dfb-8563597acbee
mod - Libs/MRML/Core/vtkMRMLDisplayableNode.cxx Diff File
mod - Libs/MRML/Core/vtkMRMLDisplayableNode.h Diff File
mod - Libs/MRML/Core/vtkMRMLStorableNode.cxx Diff File
mod - Libs/MRML/Core/vtkMRMLStorableNode.h Diff File
mod - Libs/MRML/Core/vtkMRMLTransformableNode.cxx Diff File
mod - Libs/MRML/Core/vtkMRMLTransformableNode.h Diff File

Slicer: 2145-support-for-installing-extension-from-file db4456a6

2013-07-15 11:23:55

finetjul

Details Diff
BUG: Copy NodeReferenceMRMLAttributeNames in vtkMRMLNode::Copy()

Issue 0002727

git-svn-id: http://svn.slicer.org/Slicer4/trunk@22187 3bd1e089-480b-0410-8dfb-8563597acbee
mod - Libs/MRML/Core/vtkMRMLNode.cxx Diff File

Slicer: 2145-support-for-installing-extension-from-file 7435bb67

2013-07-15 11:24:02

finetjul

Details Diff
ENH: Add support for node reference templates

In vtkMRMLSelectionNode, the exact name of the reference roles of a unit is
not known until the unit is set and observed. (it's a dynamic number of
unit reference roles). By using a special key '/' in the reference role
(e.g. "unit/"), it is possible to have multiple reference roles
(e.g. "unit/length", "unit/time"...).
Issue 0002727

git-svn-id: http://svn.slicer.org/Slicer4/trunk@22188 3bd1e089-480b-0410-8dfb-8563597acbee
mod - Libs/MRML/Core/vtkMRMLNode.cxx Diff File
mod - Libs/MRML/Core/vtkMRMLNode.h Diff File
mod - Libs/MRML/Core/vtkMRMLSelectionNode.cxx Diff File
mod - Libs/MRML/Core/vtkMRMLSelectionNode.h Diff File

Issue History

Date Modified Username Field Change
2012-11-05 05:03 lassoan New Issue
2012-11-05 05:03 lassoan Status new => assigned
2012-11-05 05:03 lassoan Assigned To => alexy
2012-11-05 11:03 jcfr Priority normal => urgent
2012-11-05 11:03 jcfr Target Version => Slicer 4.3.0
2012-11-05 11:04 jcfr Note Added: 0007053
2013-03-15 06:27 alexy Status assigned => closed
2013-03-15 06:27 alexy Resolution open => fixed
2013-03-15 06:27 alexy Additional Information Updated
2013-03-15 07:08 alexy Status closed => resolved
2013-03-19 10:43 jcfr Note Added: 0008153
2013-03-19 10:57 jcfr Note Added: 0008157
2013-03-24 13:53 pinter Note Added: 0008225
2013-03-24 13:59 lassoan Note Added: 0008226
2013-03-24 14:05 lassoan Note Added: 0008227
2013-03-24 14:05 lassoan Status resolved => assigned
2013-03-26 06:30 jcfr Note Edited: 0008226
2013-03-29 08:33 alexy Note Added: 0008263
2013-03-29 08:33 alexy Status assigned => resolved
2013-07-10 06:28 finetjul Note Added: 0008980
2013-07-10 06:33 jcfr Note Added: 0008981
2013-07-10 07:56 lassoan Note Added: 0008982
2013-07-10 08:07 finetjul Note Added: 0008983
2013-07-10 08:23 lassoan Note Added: 0008984
2014-03-06 05:18 jcfr Note Added: 0011107
2014-03-06 05:20 jcfr Status resolved => closed
2014-03-06 05:54 jcfr Fixed in Version => Slicer 4.4.0
2017-06-07 23:27 finetjul Changeset attached => Slicer 2145-support-for-installing-extension-from-file 7435bb67
2017-06-07 23:27 finetjul Changeset attached => Slicer 2145-support-for-installing-extension-from-file db4456a6
2017-06-07 23:27 finetjul Changeset attached => Slicer 2145-support-for-installing-extension-from-file 1c0a42cd