一、模块简介
Data模块是slicer中很重要也很实用的模块,它列出了当前场景中的所有对象,以节点形式表现,并且允许在模块的MRML树中对这些对象节点进行一些基本的操作,像搜索、重命名、删除移动等。
Data模块在slicer中扮演着中央数据组织点的角色,它将加载到slicer的所有数据在不同的视图中表现出来。主题分层视图( Subject Hierarchy view)就是其中一个视图,它将数据以一种易于探索的方式显示出来,并且提供了对数据节点的操作。转换分层视图(Transform Hierarchy view)支持转换链的探索。全节点视图( All Nodes view)将所有数据节点以一种非结构化的方式显示出来。
在主题分层视图( Subject Hierarchy view)中,DICOM数据会自动以一种 patient-study-series 的分层结构进行添加。非DICOM数据如果是从本地目录结构中加载的,那么它们能够被slicer自动解析并分层,也可以通过创建类似于DICOM文件的分层或文件夹手动将它们组织成一种树状结构。关于模型的存在的层次结构能够自动在主题分层视图映射出来,所以可以采用通常的方法来探索模型图集。
主题分层视图( Subject Hierarchy view)中提供了对其下数据节点的特色操作,包括克隆(cloning)、群转换(bulk transforming)、群显示/隐藏(bulk show/hide)、指定类型的特色操作(type-specific features)。还提供了节点的基本操作像删除、重命名等。附加的插件(plugins)还可以提供一些其他的指定类型的特色操作和通常操作。
二、应用方向
主题分层视图( Subject Hierarchy view):
- 用该视图可以在一个地方浏览加载到slicer中的数据对象,不同的类型用不同的图标来标识。
- 用文件夹(folders)或者病人/主题的树状结构(patient/subject trees)来组织数据便于管理和群操作。
- 对从磁盘中加载的数据节点进行可视化或者群操作处理。
- 可以很简单的显示/隐藏由可显示节点组成的分支。
- 可以很简单的对整个study(任何分支)进行转换。
- 输出为DICOM数据(编辑DICOM标签)
- 还有许多类型指定的功能可以由插件(plugins)来提供。
转换分层视图(Transform Hierarchy view):
- 管理转换链和转换分层
全节点视图( All Nodes view):
- 开发者可以将该视图作为工具来调试问题。
三、界面面板
1.Subject hierarchy
- 从DICOM中加载的数据会自动以正确的结构(patient, study, series)加入到树结构中。
- 非DICOM数据也会自动出现在Subject hierarchy面板上,有两种方式来以分层形式组织它们:
- 执行'Create hierarchy from loaded directory structure'动作,这个动作在场景的关联菜单中(在面板的空白地方右击)。这将根据节点的加载位置所在的本地文件结构来组织它们。
- 手动拖放它们到分层节点下。
- 再者,当你在创建model或者其它类型(如annotation)的分层后,这种分层结构也会在Subject hierarchy中显示。比如你手动创建一个ROI后,在annotationModule中同时你也自动创建了一个分层结构,这种分层以一种节点形式表示(vtkMRMLAnnotationHierarchyNode),那么在Subject hierarchy面板中也会看见这种分层组织结构
- 在这个面板中,节点可以被拖放到其它节点下,重新排列树结构。
- 基本操作(可以通过右击这些数据节点在关联菜单中获得):
- 转换节点或者整个分支(Transform node or branch):双击节点或分支的转换列以在转换列中进行转换,然后设置想要的转换,转换列用TransformModule的图标来表示。如果转换列不可见,需要勾选树结构下方的'Show transforms'选择框。
- 显示/隐藏节点或分支(Show/hide node or branch):点击对应节点或分支的眼图标。
- 删除(Delete)
- 重命名(Rename)
- 克隆(Clone):创建选中节点的副本,副本与原来的节点在各方面都一样,但是它的命名加有 '_Copy'后缀。
- 编辑属性(Edit properties):如果某个节点的角色已经指定了(即它的图标没有问题),那么这个动作执行后将会打开对应的Module,并且该该节点也会被该模块选中(e.g. Volumes module for volumes)。
- 创建子。。(Create child...):创建一个指定类型的节点。
- slicer刚打开的时候树中没有任何节点,可以通过右击空白区域来加入新节点,如果场景项目存在,也可以右击它来添加新节点。
- 角色以及对应的功能(每个节点都有不同类型对应不同角色):
- 'Register this...':选择该图像为固定图像用于配准,右击相应的图像为移动图像初始化配准
- 'Segment this...':允许分割该图像,例如转到Editor module中进行分割。
- 'Toggle labelmap outline display':用于labelmaps类型的Volume
2. Models: 图标,编辑属性,以及额外的提示信息
3. SceneViews: 图标,编辑属性,以及恢复场景视图。
4. Transforms: 图标,额外的提示信息,编辑属性,反转(Invert),重置为恒等(Reset to identity)。
5. Many others, such as Markups, Charts, Annotations, Tables, etc.
- 主题分层条目信息(Subject hierarchy item information):展示详细的关于选中的主题分层条目的信息
2.Transform hierarchy
- 节点:该视图列出了场景中所有可转换的节点,以一个分层树方式显示了节点之间的关系。对于是图形对象的节点,像volumes或者models,会控制它们在不同视图中(2D、3D)的显示。列表中左键双击任一条目,便可对该条目重命名(除了scene)。右键单击会弹出一个关联菜单包含不同的动作:"Insert Transform" 会创建一个身份标识的线性转换节点并将它应用于选中的节点上。"Edit properties"会打开一个特定模块,(e.g. "Volumes" for volume nodes, "Models" for model nodes, etc.)。"Rename"会打开一个对话框来重命名该节点。"Delete"会将该节点从场景中删除。在该视图中支持内部的拖放操作,在同一个父节点中移动一个节点的位置不会有什么影响,改变一个节点的父节点将会有不同的意义,取决于当前的场景模型。
- Show MRML ID's:在树状视图中显示/隐藏第二列,包含了节点的节点ID。默认是隐藏的。
- Show hidden nodes:显示/隐藏那些隐藏的节点。默认情况下只有主节点是显示的。
3.All nodes
以非结构化的方式展现场景中的所有节点,支持属性编辑、重命名和删除的操作。
4.Common
- Filter:隐藏所有与输入字符不匹配的节点,这对于快速搜索指定的节点是非常有用的。注意这里的搜索是区分大小写的。
- MRML node information:包含着两部分,这两部分都只有在选中MRML数据节点时才会显示,第一部分“Node information”,会显示选中数据节点的详细数据信息。第二部分为属性Attribute区,显示当前选中节点的属性表单,属性可以编辑(双击"Attribute value"单元格),也可以添加(with the"Add" button)或移除(with the"Remove" button)。
四、操作应用
- 从头开始创建一个新主题(new Subject)
- 创建新文件夹(new folder)
右击存在的条目或者空白区域,选择'Create new folder'。文件夹类型(folder)的分层条目使用关联菜单能够被转换为主题(Subject)或者研究(Study )分层。
- 重命名条目
右击节点,选择'Rename',或者双击节点的名字部分。
- 应用一个转换到节点或者分支上
五、开发者必晓
1.获取以及操控主题分层条目(subject hierarchy items)的代码片段
- 获取伪单subject hierarchy节点
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
- 创建主题分层条目:
# If it is for a data node, it is automatically created, but the create function can be used to set parent:
shNode.CreateItem(parentItemID, dataNode)
![](https://i-blog.csdnimg.cn/blog_migrate/e83130bbb3b0d7a87672fa6c85c32944.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6d006db7a3e73b1e2edf92dcec059476.png)
# If it is a hierarchy item without a data node, then the create function must be used:
shNode.CreateSubjectItem(parentItemID, name)
![](https://i-blog.csdnimg.cn/blog_migrate/27cade7f2c68764fbbcaa3189821e361.png)
![](https://i-blog.csdnimg.cn/blog_migrate/18bb542c78cd20e6bee5918ffa372a81.png)
shNode.CreateFolderItem(parentItemID, name)
![](https://i-blog.csdnimg.cn/blog_migrate/6b7a23e78ee8e9e1fbe43b1521123acc.png)
![](https://i-blog.csdnimg.cn/blog_migrate/920239b1c78a1822c5e866c426a54d8f.png)
shNode.CreateHierarchyItem(parentItemID, name, level)
# Advanced method to set level attribute manually (usually subject, study, or folder, but it can be a virtual branch for example)
![](https://i-blog.csdnimg.cn/blog_migrate/2bdfcbb6437ab9321938963fbdfd2ba8.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1bc475678e094032d423608a676ad8e0.png)
- 获取主题分层条目(subject hierarchy item)
# Get scene item ID first because it is the root item:
sceneItemID = shNode.GetSceneItemID()
# Get direct child by name
subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')
![](https://i-blog.csdnimg.cn/blog_migrate/9707dd3f3149de1284bfc27ec6aabbee.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4d92b0070987d09e89e85661e6bf3420.png)
# Get item for data node
itemID = shNode.GetItemByDataNode(dataNode)
![](https://i-blog.csdnimg.cn/blog_migrate/abc9818b4561ab48711e6d5c8b2d68ef.png)
# Get item by UID (such as DICOM)
itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)
itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)
# Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)
invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()
- 遍历主题层次条目的子条目
children = vtk.vtkIdList()
shNode.GetItemChildren(parent, children)
for i in xrange(children.GetNumberOfIds()):
child = children.GetId(i)
![](https://i-blog.csdnimg.cn/blog_migrate/32d9d1fb5e702166cb6e63b9864af8b7.png)
- 操作主题分层条目
# Set item name
shNode.SetItemName(itemID, 'NewName')
![](https://i-blog.csdnimg.cn/blog_migrate/b7eeebb8e88dd4b8aa0a1ca466c7ad1a.png)
# Set item parent (reparent)
shNode.SetItemParent(itemID, newParentItemID)
![](https://i-blog.csdnimg.cn/blog_migrate/13c789767dd0fb8474e4aea622f3b2ef.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6d9cc5dae14eda6809c84292ea10128f.png)
- Filter items in TreeView or ComboBox
print shTreeView.displayedItemCount() # 5
shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute
print shTreeView.displayedItemCount() # 3
shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'
print shTreeView.displayedItemCount() # 1
shTreeView.removeAttributeFilter()
print shTreeView.displayedItemCount() # 5
2.实现新插件(Implementing new plugins)
插件(Plugins)才是主题分层的真正魅力,因为它们为新的数据节点类型提供了支持,并且可以通过数据节点的关联菜单条目添加各种功能。- 用python来写插件(Writing plugins in Python:):
例子: Annotations role plugin, function plugin
- Role plugins: 为新的数据节点类型添加支持
需要定义:ownership, icon, tooltip, edit properties, help text (in the yellow question mark popup), visibility icon, set/get display visibility, displayed node name (if different than name of the node object)
在当前slicer核心模块中存在的插件:Markups, Models, SceneViews, Charts, Folder, Tables, Transforms, LabelMaps, Volumes
- Function plugins:为特定类型的节点在右击关联菜单中添加特色功能
需要定义:list of contect menu actions for nodes and the scene, types of nodes for which the action shows up, functions handling the defined action
在当前slicer核心模块中存在的插件:CloneNode, ParseLocalData, Register, Segment, DICOM, Volumes, Markups, Models, Annotations, Segmentations, Segments, etc.