Writing a Scripted Subject Hierarchy Plugin -- documentation lacking

Hi,

Recently I’ve been writing an internal-use Subject Hierarchy plugin. I ran into some difficulties that stem, IMO, from lacking documentation, so I want to share what I’ve learned with a view to getting some comments and eventually improving the docs.

The first, and most important issue, is the context. For a class to serve as a Subject Hierarchy Plugin, it needs to

  • Be written in the main file of an Extension Module
  • Be named exactly as the module, with the suffix SubjectHierarchyPlugin

That is, if your module is named Kawabanga, the plugin class must reside in Kawabanga.py and be named KawabangaSubjectHiearachyPlugin.

This is followed, but not explicitly declared, in the example plugin in the script repository; that example is also a bit misleading, because it is (correctly) described as an example for a special plugin (one that operates in views, rather than in the subject hierarchy).

Other plugins which claim to serve as examples – e.g. SegmentEditorSubjectHierarchyPlugin in the sources – don’t actually follow these rules, and so they are misleading.

When fixing the documentation, we should also modernize the examples – currently, the way to iterate over children is presented in the script repository as

children = vtk.vtkIdList()
shNode.GetItemChildren(parent, children)
for i in range(children.GetNumberOfIds()):
  child = children.GetId(i)
  ...

but with modern Python and Slicer, this can be done with

shNode.GetItemChildren(parent, children:=[])
for child in children:
  ...

I will come back to this later, but wanted to raise this while fresh in mind and maybe get some feedback.

Thanks!

Just very quickly due to not having any time today.

No documentation

You’re right, this could be improved.

That is, if your module is named Kawabanga, the plugin class must reside in Kawabanga.py and be named KawabangaSubjectHiearachyPlugin.

I’m pretty sure that this is not correct. Please look at for example SlicerHeart\ValveAnnulusAnalysis\HeartValveLib\HeartValvesSubjectHierarchyPlugin.py

but with modern Python and Slicer

Actually, I think what we’d suggest would be slicer.util.getSubjectHierarchyItemChildren, but what you’re suggesting is great too. Honestly I’d need to look at how it works exactly.

So, yes, my claim was inaccurate. The plugin class doesn’t really need to be in the same file as the main module. Its name only has to match the name of the module it is actually in, that is:

  • If the module name ends with SubjectHierarchyPlugin, the plugin class must have the same name;
  • Otherwise, the plugin class must be named as the module with the suffix SubjectHierarchyPlugin.

That is, even if your main module is Kawabanga.py, you plugin class may be named YipeeSubjectHierachyPlugin. And then the file it is defined in can be either YipeeSubjectHierachyPlugin.py or Yipee.py, but it must be one of these two.

This is enforced in qSlicerSubjectHierarchyScriptedPlugin::setPythonSource(const QString filePath)

More of this later.

1 Like