Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a parameter set selector and append the result in a table. #133

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

chir-set
Copy link
Collaborator

@chir-set chir-set commented Nov 4, 2024

StenosisMeasurement3D

  • create an MRML parameter node class
  • do not create a default parameter node in the selector
  • enforce selection of a parameter set
  • use the parameter node in logic
  • append the results in an MRML table
  • improve existing code.

@chir-set
Copy link
Collaborator Author

chir-set commented Nov 4, 2024

Hello @lassoan ,

Please consider this PR with the main purpose of adding a parameter node to the StenosisMeasurement3D module. The parameter node is mainly based on vtkMRMLCropVolumeParametersNode.

Waiting for your comments.

Regards.

@chir-set chir-set requested a review from lassoan November 4, 2024 16:55
Copy link
Contributor

@lassoan lassoan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, I don't have any problems if you merge it as is. But I added a couple of comments inline that would improve the design a bit.

void operator=(const vtkMRMLStenosisMeasurement3DParameterNode&);

std::string InputSegmentID;
vtkWeakPointer<vtkPolyData> OutputWallOpenPolyData;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think vtkSetObjectMacro/vtkGetObjectMacro is compatible with vtkWeakPointer, but even if it does not crash or behaves incorrectly, it just does not make sense.

If you use vtkSetObjectMacro/vtkGetObjectMacro then it means that vtkMRMLStenosisMeasurement3DParameterNode owns the object (the parameter node keeps a reference to the object, so the object will not be deleted until the parameter node releases it) and the vtkMRMLStenosisMeasurement3DParameterNode should use a simple pointer (that is initialized to nullptr here).

If you use a vtkSmartPointer then you can use vtkSetMacro/vtkGetMacro and the parameter node owns the object.
If you use a vtkWeakPointer then you can use vtkSetMacro/vtkGetMacro and some other object must keep a reference to the object.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed for vtkSmartPointer.

But vtkGet/SetMacro does not compile.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the error message? If adding #include <vtkSmartPointer.h> does not solve the issue then you can investigate further (copy the error message here, maybe I have an idea). But often we don't need get/set functions, as you can set the variable with a single operator=.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a typical error message:

In file included from /home/user/tmp/Slicer/SlicerExtension-VMTK/StenosisMeasurement3D/MRML/vtkMRMLStenosisMeasurement3DParameterNode.cxx:1:
/home/user/tmp/Slicer/SlicerExtension-VMTK/StenosisMeasurement3D/MRML/vtkMRMLStenosisMeasurement3DParameterNode.h:62:5: error: no viable overloaded '='
62 | vtkSetMacro(OutputWallOpenPolyData, vtkPolyData);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/arc/src/Slicer-SuperBuild9/VTK/Common/Core/vtkSetGet.h:134:18: note: expanded from macro 'vtkSetMacro'
134 | this->name = _arg;
| ~~~~~~~~~~ ^ ~~~~
/home/arc/src/Slicer-SuperBuild9/VTK/Common/Core/vtkSmartPointer.h:144:20: note: candidate function not viable: no known conversion from 'vtkPolyData' to 'const vtkSmartPointer' for 1st argument
144 | vtkSmartPointer& operator=(const vtkSmartPointer& r)
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~
/home/arc/src/Slicer-SuperBuild9/VTK/Common/Core/vtkSmartPointer.h:151:20: note: candidate template ignored: could not match 'vtkSmartPointer' against 'vtkPolyData'
151 | vtkSmartPointer& operator=(const vtkSmartPointer& r)
| ^
/home/arc/src/Slicer-SuperBuild9/VTK/Common/Core/vtkSmartPointer.h:165:20: note: candidate template ignored: could not match 'vtkNew' against 'vtkPolyData'
165 | vtkSmartPointer& operator=(const vtkNew& r)
| ^
/home/arc/src/Slicer-SuperBuild9/VTK/Common/Core/vtkSmartPointer.h:178:20: note: candidate template ignored: could not match 'U ' against 'vtkPolyData'
178 | vtkSmartPointer& operator=(U
r)
| ^
In file included from /home/user/tmp/Slicer/SlicerExtension-VMTK/StenosisMeasurement3D/MRML/vtkMRMLStenosisMeasurement3DParameterNode.cxx:1:
/home/user/tmp/Slicer/SlicerExtension-VMTK/StenosisMeasurement3D/MRML/vtkMRMLStenosisMeasurement3DParameterNode.h:63:5: error: no viable conversion from returned value of type 'vtkSmartPointer' to function return type 'vtkPolyData'
63 | vtkGetMacro(OutputWallOpenPolyData, vtkPolyData)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/arc/src/Slicer-SuperBuild9/VTK/Common/Core/vtkSetGet.h:156:12: note: expanded from macro 'vtkGetMacro'
156 | return this->name;
| ^~~~~~~~~~
/home/arc/src/Slicer-SuperBuild9/VTK/Common/DataModel/vtkPolyData.h:757:3: note: candidate constructor not viable: no known conversion from 'vtkSmartPointer' to 'const vtkPolyData &' for 1st argument
757 | vtkPolyData(const vtkPolyData&) = delete;
| ^ ~~~~~~~~~~~~~~~~~~
/home/arc/src/Slicer-SuperBuild9/VTK/Common/Core/vtkSmartPointer.h:197:3: note: candidate function
197 | operator T*() const noexcept { return static_cast<T*>(this->Object); }
| ^
5 errors generated.

I'll probably not use the macro.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may need to add #include <vtkPolyData.h> as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vtkPolyData.h is already included. vtkSmartPointer.h and vtkSetGet.h do not help.

I'm using clang version 18.1.8, don't know if it's the problem.

Dropping the macro is probably the simplest solution.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grepping through the Slicer code base, it seems that vtkSet/GetMacro is always used for data types like int, double... like here, and vtkSet/GetObjectMacro is always used for objects created from high-level classes like here.


QObject::connect(d->parameterSetSelector, SIGNAL(currentNodeChanged(vtkMRMLNode*)),
this, SLOT(setParameterNode(vtkMRMLNode*)));

// Put p1 and p2 ficucial points on the tube spline at nearest point when they are moved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We always need to consider the GUI as optional. The module should be fully functional without instantiating a GUI widget. Therefore, you need to put in the logic things like observing some node and updating the scene content when the observed node is modified.

There are convenience features in module logic classes that make it relatively simple to observe modifications of all nodes of a certain type (see vtkSetAndObserveMRMLNodeEventsMacro and ProcessMRMLNodesEvents and how it is used for example in vtkSlicerMarkupsLogic).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using vtkObserveMRMLNodeEventsMacro in ProcessMRMLNodesEvents

How does it differ from vtkSetAndObserveMRMLNodeEventsMacro?

Copy link
Contributor

@lassoan lassoan Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vtkSetAndObserveMRMLNodeEventsMacro is useful when you want to keep a pointer to a node and observe events that the node invokes. The macro does everything you need: removes observations from the previously observed node, releases reference from the old node, adds observations and reference to the newly selected node.

vtkObserveMRMLNodeEventsMacro just adds observations to a node.

@chir-set
Copy link
Collaborator Author

chir-set commented Nov 6, 2024

Thank you for this insightful review, I'll fix all these.

@chir-set chir-set force-pushed the ParameterSetCpp_SM3D branch 2 times, most recently from a3d0ba9 to 44945da Compare November 8, 2024 19:47
@chir-set
Copy link
Collaborator Author

chir-set commented Nov 8, 2024

Hi @lassoan ,

I made all the changes, moving much code in logic. Testing from Python is successful. I'm ready to change other things per your instructions.

Thanks and regards.

@lassoan
Copy link
Contributor

lassoan commented Nov 8, 2024

Great! I'll review your changes in details, so if you have any specific questions then let me know.

@chir-set chir-set force-pushed the ParameterSetCpp_SM3D branch 2 times, most recently from ff1e4a6 to 3ec9bfa Compare November 9, 2024 13:04
StenosisMeasurement3D

 - create an MRML parameter node class
 - do not create a default parameter node in the selector
 - enforce selection of a parameter set
 - use the parameter node in logic
 - append the results in an MRML table
 - improve existing code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants