3DSlicer16:数据类型MRML
1.Slicer MRML数据类型综述
- MRML提供API(应用程序接口)管理医学图像数据类型(Volume、Model、Transform、Fiducial、Camera等)和它们的可视化;
- 每种数据类型都用一个特定的MRML节点表示;
- MRML场景就是MRML节点的集合;
- Slicer的MRML数据模型(data Model)独立于Slicer系统的可视化组件Visualization和算法组件Algorithm;
- 其他的Slicer组件,Logic和Qt Widget观测MRML场景和每个节点的变化。
2.MRML 场景
- MRML场景管理MRML节点:添加、删除、寻找等;
- MRML Scene provides persistence of MRML nodes (reading/writing to/from XML file)
3.MRML 节点
- MRML节点用于存贮Slicer应用的状态,包括原始数据和可视化、参数。一组存储核心Slicer Module状态的的核心MRML节点如下所示:
- MRML节点以C++类等级的形式被组织,所有的子类均继承vtkMRMLNode;
- 所有的MRML节点必须应用某种标准的API:ReadAttributes、WriteAttributes、Copy等;
- 相同的数据可以用不同的方式进行可视化,并储存成不同的类型。因此,信息分别以三种不同节点类型进行存储:
- 数据节点:存储原始数据,例如vtkMRMLScalarVolumeNode存储体素、spacing、位置、方向
- 显示节点:描述了数据怎么样被可视化,对于相同的原始数据可能会有很多的显示节点,例如一个节点进行体绘制、另外一个节点用于显示一张图像
- 存储节点:描述数据应该如何永久性存储到磁盘中,文件格式、文件名
- 当一个数据节点被创建的时候,我们必须创建相应的显示节点与数据存储节点,方便进行合理的可视化和保存文件。MRMLLogic会提供函数——创建一个节点并与显示节点&数据节点关联。注意:在一些情况下,Slicer会检测是否显示节点与存储节点遗失,并尝试创建默认节点,但是作为开发人员我们不应该依赖这种错误校正机制。
4.MRML节点属性
MRML节点可以成对存储自定义属性:属性名+属性值。To avoid name clashes custom modules that adds attributes to nodes should prefix the attribute name with the module's name and the '.' character. Example: the DoseVolumeHistogram module can use attribute names such as DoseVolumeHistogram.StructureSetName, DoseVolumeHistogram.Unit, DoseVolumeHistogram.LineStyle.
5.MRML节点引用
这里有两种机制来指定节点间是相关的:层次结构节点&节点引用。相比之下,节点引用更简单。MRML节点可以利用节点引用API引用或者观测其他的MRML节点。这个框架会自动处理:
- 节点引用的读、写、复制
- 场景导入更新引用
- 增加或删除节点
一个节点可能引用很多节点,每个节点都扮演了不同的角色,并且每个节点都有唯一的字符串进行处理。
数据节点可以选择性地应用接口:如Displayable、Storable、Transformable。每一个接口都有自己的需求。例如,变换模块接口期待与变换节点相关联。这种关联就是通过创建MRML Reference完成的。5.1 MRML Reference:API描述
上面的节点应用API功能是在vtkMRMLNote基类中实现的。The only thing that needs to happen in thederived MRML node class(usually in the constructor of the class) is a call tovtkMRMLNode::AddNodeReferenceRole(const char *referenceRole, const char *mrmlAttributeName) that takes a unique string defining the reference role between this node and the referenced node, and a MRML attribute name for storing the reference in the .mrml file.The only other call that is needed is either:
vtkMRMLNode* SetAndObserveNodeReferenceID(const char* referenceRole , const char* referencedNodeID, vtkIntArray *events=0);
or
vtkMRMLNode* AddAndObserveNodeReferenceID(const char* referenceRole , const char* referencedNodeID, vtkIntArray *events=0);vtkMRMLNode也提供了虚回调函数,可以在继承类中拓展:OnNodeReferenceAdded(vtkMRMLNodeReference *reference) OnNodeReferenceRemoved(vtkMRMLNodeReference *reference) OnNodeReferenceModified(vtkMRMLNodeReference *reference)
默认情况下,这些方法生成一下事件:
vtkMRMLNode::ReferenceAddedEvent vtkMRMLNode::ReferenceRemovedEvent vtkMRMLNode::ReferenceModifiedEvent
在继承类中,这些方法可以采用VTKMRMLNode拓展,以允许查询节点的引用。
vtkMRMLNode成员的完整列表参考如下网址,包括所有继承的成员:http://apidocs.slicer.org/master/classvtkMRMLNode-members.html目前,下述的几个MRML节点是采用MRML节点引用API实现的:
- vtkMRMLStorableNode
- vtkMRMLTransformableNode
- vtkMRMLDisplayableNode
其他引用MRML节点,例如vtkMRMLColorTableNode, vtkMRMLDiffusionTensorDisplayPropertiesNode,目前还没有只用这种API。
5.2 MRML Reference:示例
vtkMRMLTransformableNode implementation:
http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLTransformableNode.h?view=log
vtkMRMLDisplayableNodeimplementation:
http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLDisplayableNode.h?view=log
vtkMRMLStorableNodeimplementation:
http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLStorableNode.h?view=log
6.MRML事件与观测者Event-Observe
- MRML场景和各个节点的改变会传递给其他观测者节点,GUI和Logic对象通过vtk事件、命令-观测者机制。
- 使用vtkAddObserver()和InvokeEvent()方法。vtkSetMicro生成ModifiedEvent。
- 对于MRML,命令-观测者机制采用助手vtkObserverManager、类、MRML观测者宏、ProcessMRMLEvent方法实现。
- 观测者应该存储一个注册的指针,该指针指向MRML节点,防止一个已经删除对象的回调函数。
- MRML 观察者宏定义位于 Libs/MRML/vtkMRMLNode.h
- vtkSetMRMLObjectMacro - 注册 MRML节点
- vtkSetAndObserveMRMLObjectMacro - 注册 MRML 节点,并为vtkCommand::ModifyEvent增加一个观察者
- vtkSetAndObserveMRMLObjectEventsMacro - 注册MRML节点并为一个指定的事件集合设置观测者
- SetAndObserveMRMLScene[Events]() 方法在GUI/Logic中使用,用于观察变化、新场景、增加节点等事件
- ProcessMRMLEvents method在MRML节点、Logic、GUI类中实现,在观察节点中处理事件
7.创建自定义的MRML节点类
- 自定义MRML节点为模块参数提供了永久性存储
- 自定义MRML节点应该使用RegistraterNodeClass()在MRML场景中注册,因此他们可以从一个场景文件中恢复或者保存
- 这个类应该实现以下方法:
- CreatNodeInstance()-与VTK的New()相似,只不过不是静态的
- GetNodeTagName()-为这个节点返回一个独一无二的XML标签
- ReadXMLAttributes()-从XML文件中读取节点属性,如name-value
- WriteXML()-将节点属性写入到输出流
- Copy()-拷贝节点属性
- 如果该节点已经引用其他的节点,那么下面的方法也应该实现:
- UpdateReferenceID()-更新对另一个节点已经存储的应用
- UpdataScene()-依赖这个节点更新场景中的其他节点
- 向MRML场景中添加新的节点
一个实现自定义MRML节点的例子:vtkMRMLGradientAnisotropicDiffusionFilterNode inModules/GradientAnisotropicDiffusionFilter directory.
8.MRML层次结构节点
http://apidocs.slicer.org/master/classvtkMRMLHierarchyNode.html
9.MRML:Developer FAQ
9.1 如何在场景中增加一个MRML节点?
- 通用的模式
vtkNew<vtkMRML???Node> nodeToAdd; ... mrmlScene->AddNode(nodeToAdd.GetPointer());
- 在场景中添加一个多边形数据?
vtkNew<vtkMRMLModelNode> modelNode; modelNode->SetPolyData(polyData); mrmlScene->AddNode(modelNode.GetPointer());
- 从文件中加载一个多边形数据?
vtkSlicerModelsLogic* modelsLogic = ...; //modelsLogic->SetMRMLScene(mrmlScene); modelsLogic->AddModel(polyDataFileName);
9.2 加载一个MRML场景时,如果碰到以下信息该怎么办?
ERROR: In /path/to/VTK/Imaging/vtkImageMapToColors.cxx, line 153 vtkImageMapToColors (0x268f190): RequestInformation: No LookupTable was set but number of components in input doesn't match OutputFormat, therefore input can't be passed through!ERROR: In /path/to/VTK/Imaging/vtkImageExtractComponents.cxx, line 239 vtkImageExtractComponents (0x26947e0): Execute: Component 1 is not in input.ERROR: In /path/to/VTK/Imaging/vtkImageExtractComponents.cxx, line 239 vtkImageExtractComponents (0x26947e0): Execute: Component 1 is not in input.[...]
确保每一个VolumeDisplay节点都设置了ColorNodeRef属性。
9.3 如何在2D视窗中改变立体?
appLogic = slicer.app.applicationLogic() selectionNode = appLogic.GetSelectionNode() selectionNode.SetReferenceActiveVolumeID(bg) selectionNode.SetReferenceSecondaryVolumeID(fg) appLogic.PropagateVolumeSelection()
3DSlicer16:数据类型MRML相关推荐
- 3DSlicer33:Adding MRML
1.Adding in MRML to Slicer MRML是Slicer中用到的场景描述,并映射到他的数据模型.MRML库提供了API管理医学图像数据类型和可视化,数据类型包含Volume.mod ...
- Postman使用Date数据类型,Postman发送Date类型数据,Postman模拟前端调用
Postman使用Date数据类型: 在form-data数据类型下,使用 2021/7/7 11:11:00 (yyyy/MM/dd HH:mm:ss) 的数据格式即可 如下: 在json数据格式中 ...
- 大数据中用到的新的数据类型bigint、decimal、smallint、tinyint
在对比oracle数据库和大数据库的时候,发现了几个用以存放数字的新的类型bigint.decimal.smallint.tinyint,为了对比之间的不同,我进行了统计 bigint 可以精确的表示 ...
- NumPy — 创建全零、全1、空、arange 数组,array 对象类型,astype 转换数据类型,数组和标量以及数组之间的运算,NumPy 数组共享内存
NumPy 简介 一个用 python 实现的科学计算包.包括: 1.一个强大的 N 维数组对象 Array : 2.比较成熟的(广播)函数库: 3.用于整合 C/C++ 和 Fortran 代码的工 ...
- 【JavaScript总结】JavaScript语法基础:数据类型
------>数据类型有哪些? ->基本类型:数字类型,布尔类型,字符串类型 ->引用类型:对象类型,函数类型 ->空类型:null 和 undefined ->运算符: ...
- 数据类型对应的字节数
20210622 https://www.icode9.com/content-4-421680.html 32位和64位常用数据结构所占字节数 20210126 1 2 4 8 1248 刚好都是2 ...
- tensorflow2.0 基础一 常用数据类型及转换
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_43619065/arti ...
- 深入浅出Redis五种基本数据类型
文章目录 1.String SDS(Simple Dynamic String) 2.RedisDB设计 3.List 4.Hash 5.Set intset 6.ZSet skiplist 1.St ...
- TVM自定义数据类型
TVM自定义数据类型 本文将介绍"自定义数据类型"框架,该框架可在TVM中使用自定义数据类型. 介绍 在设计加速器时,关键是如何近似地表示硬件中的实数.这个问题具有长期的行业标准解 ...
最新文章
- 推荐8个非常有逼格的实用软件,让你的办公更高效
- 什么是COM与DCOM
- Python之几种常用模块
- EasyUI-datagrid 对于展示数据进行处理(formatter)
- flex的12个属性
- vue中文件上传方法
- 小程序正式发布后,打开白屏(已解决)
- Java前端Rsa公钥加密,后端Rsa私钥解密(支持字符和中文)
- 16.看板方法---三类改进机会
- .gen格式文件读取,完成兰伯特和墨卡托投影转换
- Axure share 二三事
- 网易云信浏览器WebRTC视频聊天集成
- 数据挖掘项目---航空公司客户价值分析
- 人民币兑换菲律宾比索去哪些银行?
- wii手柄_Wii时代的隐藏宝石
- 三国志战略版:Daniel_张角分析
- 为什么需要制定计划?
- 阵列卡u盘安装系统步骤_最简单实用的raid重装系统图文教程
- Uber 四年时间增长近 40 倍,背后架构揭秘
- 2021语言与智能技术竞赛:机器阅读理解任务 实验报告
热门文章
- 细说Sql Server中的视图(下)转载
- Java基础 之软引用、弱引用、虚引用
- 配置单节点伪分布式Hadoop
- Linux常用命令笔记---故障排除
- hdu 1516(编辑距离+记录路径)
- hdu 3577(线段树区间更新)
- input标签加disabled属性后无法获得其value值
- NYOJ 56 阶乘因式分解(一)
- hdu 1722 Cake 数学题
- Aspose.Words提示The document appears to be corrupted and cannot be loaded.