概要
在用DCMTK库来写query和retrieve的时候查询条件的定义不是很清楚,DICOM的query和数据库的select 有什么区别呢?
Query即C-Find, Retrieve 即C-Move, 在放射影像设备、系统中是仅次于C-store(发送影像)应用最多的命令, 相较c-sore, c-find/c-move 要复杂很.....
Query/retrieve 简化序列图 (只有一个c-move-rsp 回合)
对于SCU (发起方)
通俗来讲Query 是指请求对方系统把 请求某个级别(Patient/Study/Series/Image)的信息传送给自己。当然也可以进行关联查询要求对方把各个级别的信息都返回给自己。
Retrieve是指SCU通过Query 拿到信息后,要求对方根据请求级别 (Patient/Study/Series/Image) 发送影像给己方。
对于SCP (服务提供方)
需要提供各个级别的服务供SCU Query/Retrieve.
C-Find/C-Move 有几个重要的概念
一个是 模型(Information model),
Patient root
Study root
Patientstudy root
一个是 级别(Query/retrieve level)
Patient level, study level, series level, image level
Patient root 下可有包含patient Level 在内的四个level
Study root 下只有三个level, study root 下不能q/r patient level 信息与影像。
C-find
既然需要依据某个条件查询一组或某个patient/study/series/image, 必须需要一个或一组查询键值, 同时需要告诉对方应该返回什么, 还有怎样区分每组数据。DICOM 中定义的query key, return key and unique key.
Unique key 为 patient id, study instance UID, series instance UID, SOP instance UID.
Query key 对应每个level 有不同的值,常见的比如检查级的studydate, 序列级的modality等,具体参见DICOM和IHE.
Unique key 必须在返回列中,否则SCU无法区分各组数据。
有些Q/R SCP 支持关联查询,SCU 可以根据Study level的query key来获取series.
C-move 相对简单
SCU 发送请求前,启动一个storage SCP 用于接收影像,
依据c-find 的返回结果,读取unique key,
Patient root
Patient level Patient id
Study level patient id, study instance UID
Series level patient id, study instance UID, series instance UID
Image level patient id, study instance UID, series instance UID, SOP instance UID
Study root
Study level study instance UID
Series level study instance UID, series instance UID
Image level study instance UID, series instance UID, SOP instance UID
每个level, 自己及上一个级别的unique key 必须提供作为query key.
C-move 中还有一个概念叫Retrieve Destination AE. 通俗讲,就是告诉对方应该发送影像到什么地方。对于SCU, 通常它可以让他发送给自己,也可以让它发送给另一个AE(甚至另一台机器,系统)。这一点也是C-move 和C-Get的区别所在,C-get 只能要求对方发给自己。
Q/R SCU告诉对方(Q/R SCP) unique key 和retrieve destination, SCP通过解析retrieve destination AE title 获取在SCP方注册的IP和端口,发送影像至此storage SCP, 同时发送c-move-rsp 到 Q/R SCU. 当影像发送结束后会发送实际统计结果至Q/R SCU.
我们来一个简单有查询定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// Fill the query object DCXOBJ obj = new DCXOBJ(); DCXELM el = new DCXELM(); el.Init(( int )DICOM_TAGS_ENUM.QueryRetrieveLevel); el.Value = "PATIENT" ; obj.insertElement(el); el.Init(0x00100010); el.Value = "R*" ; obj.insertElement(el); el.Init(0x00100020); obj.insertElement(el); el.Init(( int )DICOM_TAGS_ENUM.PatientsSex); obj.insertElement(el); el.Init(( int )DICOM_TAGS_ENUM.PatientsBirthDate); obj.insertElement(el); |
相对应的SQL语句就是:
1
2
3
|
SELECT [PATIENT NAME] , [PATIENT ID], [PATIENT SEX], [PATIENT BIRTH DATA] FROM PATIENT WHERE [PATIENT NAME] like "R%" |
下面是Study层次的实例图
// Fill the query object DCXOBJ obj = new DCXOBJ(); DCXELM el = new DCXELM(); |
|
el.Init((int)DICOM_TAGS_ENUM.studyInstanceUID); obj.insertElement(el); |
SELECT [STUDY INSTANCE UID], |
el.Init((int)DICOM_TAGS_ENUM.StudyDate); obj.insertElement(el); |
[STUDY DATE], |
el.Init((int)DICOM_TAGS_ENUM.StudyDescription); obj.insertElement(el); |
[STUDY DESCRIPTION], |
el.Init((int)DICOM_TAGS_ENUM.ModalitiesInStudy); obj.insertElement(el); |
[MODALITIES IN STUDY] |
el.Init((int)DICOM_TAGS_ENUM.QueryRetrieveLevel); el.Value = "STUDY"; obj.insertElement(el); |
FROM STUDY |
el.Init((int)DICOM_TAGS_ENUM.patientName); el.Value = "REIMOND^GOLDA"; obj.insertElement(el); |
WHERE [PATIENT NAME] = ‘REIMOND^GOLDA’ |
el.Init((int)DICOM_TAGS_ENUM.patientID); el.Value = "123456789"; obj.insertElement(el); |
AND [PATIENT ID] = ‘123456789’ |
以上例子就相当于是
1
2
3
|
SELECT [PATIENT NAME] , [PATIENT ID], [STUDY INSTANCE UID], [STUDY DATE], [STUDY DESCRIPTION], [MODALITIES IN STUDY] FROM STUDY WHERE [PATIENT NAME] = ‘REIMOND^GOLDA’ AND [PATIENT ID] = ‘123456789’ |
以下是where时候的参照表
符号 |
意思 |
相当于SQL 的意思 |
* |
零个或更多的字符,简单的说n个字符. |
WHERE PATIENT NAME LIKE “COHEN%” |
? |
一个字符 |
“COH?N” 可以符合 “COHEN” 和 “COHAN” 还有这个 “COH N” 我不建议使用这个 |
- |
对于时间和日期来的描述 FROM – TO 以下格式 YYYYMMDD-YYYYMMDD |
WHERE STUDY DATE BETWEEN 19950101 AND 20110911 |
YYYYMMDD- |
WHERE STUDY DATE >= 19950101 |
|
-YYYYMMDD |
WHERE STUDY DATE <= 20110911 |
|
\ |
符合条件的值 LOCALIZER\AXIAL |
WHERE IMAGE TYPE in (‘LOCALIZER’, ‘AXIAL’) |
以下这张图展示了query的level
以下是一个模型来验证query的level
UID |
Name |
Query Levels |
Comment |
1.2.840.10008.5.1.4.1.2.1.1 |
Patient Root Query/Retrieve Information Model - FIND |
PATIENT STUDY SERIES IMAGE |
Use it! |
1.2.840.10008.5.1.4.1.2.1.2 |
Patient Root Query/Retrieve Information Model - MOVE |
PATIENT STUDY SERIES IMAGE |
Use it! |
1.2.840.10008.5.1.4.1.2.2.1 |
Study Root Query/Retrieve Information Model - FIND |
STUDY SERIES IMAGE |
Use it if Patient root doesn’t work for you |
1.2.840.10008.5.1.4.1.2.2.2 |
Study Root Query/Retrieve Information Model - MOVE |
STUDY SERIES IMAGE |
Use it if Patient root doesn’t work for you |
1.2.840.10008.5.1.4.1.2.3.1 |
Patient/Study Only Query/Retrieve Information Model - FIND (Retired) |
PATIENT STUDY |
Don’t use |
1.2.840.10008.5.1.4.1.2.3.2 |
Patient/Study Only Query/Retrieve Information Model - MOVE (Retired) |
PATIENT STUDY |
Don’t use |
参考资料
1、http://dicomiseasy.blogspot.com/2012/01/dicom-queryretrieve-part-i.html
2、http://blog.csdn.net/lucky2all/article/details/3307753
欢迎各位参与讨论,如果觉得对你有帮助,请点击 推荐下,万分谢谢.
作者:spring yang
出处:http://www.cnblogs.com/springyangwc/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
ClearCanvas DICOM 开发系列 一
概述
C#开源的DICOM server.支持影像处理、影像归档、影像管理、影像传输和影像浏览功能。开源代码可学习地方很多。
官方网站:http://www.clearcanvas.ca
building ImageViewer 的代码,
1、打开ImageViewer.sln 在 /Trunk/ImageViewer 用VS2008编译它.
2、运行ClearCanvas.Desktop.Executable Bin\debug 或Bin\Release下的项目.
- 编译通过ImageServer.sln 在 /Trunk/ImageServer
- 修改 connectionStrings在ImageServer_Shreds_dist.config 的user 和 password 在你安装了ImageServer数据库后.
- 编辑/Trunk/ImageServer/Executable/Logging.config 的ConnectionString 的 user 和 password .
- 编译通过这个项目
- 开启 ClearCanvas.ImageServer.ShredHostService ,运行里面的wcf server,可以在Bin\Log 看到开启后的日志.
结果如下
运行 ClearCanvas.Desktop.Executable 的结果如下
测试往Server加入.dcm文件的代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
[TestFixture] public class ScuTests : AbstractTest { [TestFixtureSetUp] public void Init() { _serverType = TestTypes.Receive; } [TestFixtureTearDown] public void Cleanup() { } TestTypes _serverType; public IDicomServerHandler ServerHandlerCreator(DicomServer server, ServerAssociationParameters assoc) { return new ServerHandler( this , _serverType); } private StorageScu SetupScu() { StorageScu scu = new StorageScu( "TestAe" , "AssocTestServer" , "localhost" , 104); IList<DicomAttributeCollection> list = SetupMRSeries(4, 2, DicomUid.GenerateUid().UID); foreach (DicomAttributeCollection collection in list) { DicomFile file = new DicomFile( "test" , new DicomAttributeCollection(), collection); file.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; file.MediaStorageSopClassUid = SopClass.MrImageStorage.Uid; file.MediaStorageSopInstanceUid = collection[DicomTags.SopInstanceUid].ToString(); scu.AddStorageInstance( new StorageInstance(file)); } return scu; } [Test] public void ScuAbortTest() { int port = 2112; /* Setup the Server */ ServerAssociationParameters serverParameters = new ServerAssociationParameters( "AssocTestServer" , new IPEndPoint(IPAddress.Any, port)); byte pcid = serverParameters.AddPresentationContext(SopClass.MrImageStorage); serverParameters.AddTransferSyntax(pcid, TransferSyntax.ExplicitVrLittleEndian); serverParameters.AddTransferSyntax(pcid, TransferSyntax.ExplicitVrBigEndian); serverParameters.AddTransferSyntax(pcid, TransferSyntax.ImplicitVrLittleEndian); _serverType = TestTypes.Receive; DicomServer.StartListening(serverParameters, ServerHandlerCreator); StorageScu scu = SetupScu(); IList<DicomAttributeCollection> list = SetupMRSeries(4, 2, DicomUid.GenerateUid().UID); foreach (DicomAttributeCollection collection in list) { DicomFile file = new DicomFile( "test" , new DicomAttributeCollection(),collection ); file.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; file.MediaStorageSopClassUid = SopClass.MrImageStorage.Uid; file.MediaStorageSopInstanceUid = collection[DicomTags.SopInstanceUid].ToString(); scu.AddStorageInstance( new StorageInstance(file)); } scu.ImageStoreCompleted += delegate ( object o, StorageInstance instance) { // Test abort scu.Abort(); }; scu.Send(); scu.Join(); Assert.AreEqual(scu.Status, ScuOperationStatus.NetworkError); // StopListening DicomServer.StopListening(serverParameters); } } |
如果直接是filePath的话也可以这样
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public class ImageStoreDAL { private ConnectModel _connectModel; public ImageStoreDAL(ConnectModel connectModel) { _connectModel = connectModel; } public ConnectModel ConnectModelInstance { get { return _connectModel; } set { _connectModel = value; } } private StorageScu SetupScu( string filePath) { StorageScu scu = new StorageScu(_connectModel.ClientAETitle, _connectModel.RemoteAE, _connectModel.RemoteHost, _connectModel.RemotePort); DicomFile file = new DicomFile(filePath); scu.AddStorageInstance( new StorageInstance(file)); return scu; } public ScuOperationStatus ImageStoreByFilePath( string filePath) { StorageScu scu = SetupScu(filePath); scu.Send(); return scu.Status; } } |
spring yang
Making Time for the MITs (Most Important Things)
DICOM简介
原因
马上要做PACS(Picture Archiving and Communication Systems的缩写,意思为影像归档和通信系统。)开发了,先学些DICOM资料,暂时先记录在这里.
概要
DICOM是Digital Imaging and Communications in Medicine的英文缩写,即医学数字成像和通信标准。是ACR(American College of Radiology,美国放射学会)和NEMA(National Electrical Manufactorers Association,国家电子制造商协会)为主制定的用于数字化医学影像传送、显示与存储的标准。在DICOM标准中详细定义了影像及其相关信息的组成格式和交换方法,利用这个标准,人们可以在影像设备上建立一个接口来完成影像数据的输入/输出工作。
DICOM标准以计算机网络的工业化标准为基础,它能帮助更有效地在医学影像设备之间传输交换数字影像,这些设备不仅包括CT、MR、核医学和超声检查,而且还包括CR、胶片数字化系统、视频采集系统和HIS/RIS信息管理系统等。
该标准1985年产生。目前版本为2003年发布的DICOM 3.0 2003版本。
DICOM技术概要及特点
◆ 在应用层上通过服务和信息对象主要完成五个方面的功能:
◆ 传输和存储完整的对象(如图像、波形和文档)。
◆ 请求和返回所需对象。
◆ 完成特殊的工作(如在胶片上打印图像)。
◆ 工作流的管理(支持WORKLIST和状态信息)。
◆ 保证可视图像(如显示和打印之间)的质量和一致性。
◆ 参照软件工程面向对象的的方法。如采用实体-关联(E-R)模型、详细定义对象及其属性、服务对象对类(SOP)、消息交换以及工作流程等。
◆ 通过消息、服务、信息对象及一个良好的协商机制,独立于应用的网络技术(不受具体网络平台限制),可以点对点、点对多点、多点对点多种方式确保兼容的工作实体之间服务和信息对象能有效地通信。不仅能实现硬件资源的共享。而且不同于一般分布式对象或数据库管理只在低层自动存取单独的属性,而在病人、检查、结构化报告(SR)、工作流等高层管理上规范服务。是一个基于内容的医学图像通信标准。
◆ DICOM不规范应用系统的结构,也不规范具体的功能需求。例如,图像存储只定义传输和保存所必须的信息项目,而不说明图像如何被显示和作注解。
◆ DICOM目前16章内容每章讲述某一方面的规范,各章较为独立但又互有联系。这样便于修改扩充。只有将所有章节紧密联系起来才能勾画出标准的体系结构和整体内容。
DICOM设计
DICOM核心类
DICOM服务类
证实(verification)服务类
存储(storage)服务类
查询/检索(query/retrieve)服务类
检查内容通知(study content notification)服务类
患者管理(patient management)服务类
检查管理(study management)服务类
结果管理(results management)服务类
打印管理(print management)服务类
媒质存储(media storage) 服务类
存储责权管理(storage commitment) 服务类
基本工作列表管理(basic worklist management) 服务类
队列管理(queue management) 服务类
灰度软拷贝表达状态存储(Grayscale Softcopy Presentation State Storage)服务类
结构化报告存储(Structured Reporting Storage)服务类
缩略语解释
- HIS=医院信息系统
- PACS=医学影像归档与传输系统
- LIS=检验信息系统
- RIS=放射信息系统
- CIS=临床信息系统
HIS最大,是全医院的
PACS和RIS基本上是放射科(或者更准确地说是影像科室的)
LIS自然是检验科室的
CIS是以病人为中心的临床系统,包括以上全部和电子病历在内。
DICOM 的 4 个内容层次:
1. Patient (病人)
2. Study (检验)
3. Series (系列)
4. Image (图像)
标准中涉及的基本概念和定义
DICOM标准涉及到医学图像、数据通信、管理信息系统等领域,在标准中又采用了面向对象的描述方法和E-R (Entity-Relation)模型,从而引入了大量的各专业方面的术语,给标准的阅读和理解带来困难。下面简要地将标准中涉及的常用的技术词汇和缩略语给予解释。
1. 实体(Entity): 表示一个或一类有相同特性个体的应用对象。在计算机系统分析中,凡是可以区别并被人们识别的事、物、概念等,都可以被抽象为实体。实体一般具有若干特征,称为属性。如: 患者是一个实体,具有姓名、性别、年龄等属性。图像也是一个实体,它有图像尺寸、图像数据等属性。
2. 联系(Relation): 表示实体之间的相互关系。如患者实体与分析实体之间存在着引用联系,打印机实体和胶片实体之间存在着打印的联系。
3. E-R模型: 描述现实世界的一种信息模型。通过定义实体以及实体间的联系,表现系统的需求和功能。通常以E-R图的方式表示。在DICOM中,用方框表示实体,菱形表示联系,用带箭头或不带箭头的线段将实体(方框)与联系(菱形)连接表示它们之间存在联系。这是面向对象的分析方法所采用的主要表示方法,是对客观世界的一种抽象。
4. 对象(Object): 外部世界事物在计算机内部的表示,是事物属性值和处理方法的集合。对象具有封装和继承的特征。封装是指对象将属性和方法集合在一起,一般情况下只提供给自己和派生对象使用。继承是指当一个对象是由另一个对象(父对象)派生出时,它就自动具有父对象所具有的属性和方法。面向对象的方法就是以对象技术为中心,分析系统中各种信息之间的关系,抽象出系统各层次的对象模型,给出准确的系统描述,并在计算机系统中给予实现。应用面向对象的方法,可以提高开发效率,实现软件复用。
5. 信息对象定义(Information Ob-ject Definition,IOD): 信息实体的抽象,是DICOM命令的作用受体。
6. 服务(Service): 某对象为其它对象或程序提供的功能。当要求使用此功能时称申请服务,申请服务的对象称服务用户,而能完成该功能的对象是服务的提供者。
7. 服务对象对(Service Object Pair,SOP): DICOM信息传递的基本功能单位。包括一个信息对象和一组DICOM消息服务元素。
8. 协议: 计算机网络中为保证能正确地传输数据而必须共同遵守的通信规则和格式。
9. ISO-OSI: 国际标准化组织(ISO)所定义的开放系统互联(OSI)的七层网络参考模型。作为一个严格的网络模型,对于计算机网络的研究和发展起了重要的作用,但是由于种种原因在实际中并未得到广泛的普及使用。DICOM标准在制定时,OSI正是发展的高潮,因此也作为DICOM中主要的网络参考模型。
10. TCP/IP: 是传输控制协议/互联网协议,它首先在UNIX系统中使用,随后成为计算机网络中不同种类计算机之间通信的主要通信协议,是互联网的基础。
应用
毫无疑问,DICOM是医学图像信息系统领域中的核心,它主要涉及到信息系统中最主要也是最困难的医学图像的存储和通信,可直接应用在放射学信息系统(RIS)和图像存档与通信系统(PACS)中。DICOM也是研究和开发具有网络连接功能,实现信息资源共享的新型医疗仪器的技术基础。医疗仪器在朝着自动化、智能化发展的同时,也在向着具有通信能力的遥控遥测和信息远程获取的网络功能发展,医疗仪器既是医疗信息系统中的信息源,又是系统中的信息使用者,是信息系统中的一个主要环节,网络化的医疗仪器对医学信息系统的重要性是不言而喻的。
DICOM标准的另一个特点是它定义在网络通信协议的最上层,不涉及到具体的硬件实现而直接应用网络协议,因此与网络技术的发展保持相对独立,可以随着网络性能的提高而使DICOM系统的性能立即得到改善。DICOM尽管提供了OSI的网络模型,但现在实际上网络绝大部分都是在TCP/IP协议下构成的,网络硬件采用的形式可以多种多样,如100M的双绞线100Base-T,光纤FDDI,综合业务数字网ISDN,T1线路等,还有速度较低的10兆网10Base-T和电话线路。只要设备具有支持TCP/IP协议的网络接口,在软件的支持下,就可以做到像PC机一样实现“即插即用”,非常方便地加入到医学信息系统的网络中。在这样的意义下,用DICOM实现的医疗信息系统,无论是RIS还是PACS,都具有类似的结构,如图2所示:
在采用DICOM标准的信息网络系统中,所有DICOM设备之间都可以按照DICOM的网络上层协议进行互相连接和操作。临床医生可以在办公室查看B超设备的图像和结果,可以在CT机上调用核磁共振图像进行图像的叠加融合,也可以通过网络调用存储在其他医院的图像结果。无论是本院、本地还是相距很远的外地,DICOM设备都可以通过网络相互联系,交换信息。
由于提供了统一的存储格式和通信方式,普及DICOM标准,可以简化医疗信息系统设计,避免许多重复性的工作,加快信息系统的开发速度。对于实现无纸化、无胶片化的医院和远程医疗系统的实施将会起极其重要的作用。
参考文献