目录
一、概述
二、存储服务类(Storage Service Class)
存储操作(C-STORE)
确认操作(C-STORE-RSP)
三、查询/检索服务类(Query/Retrieve Service Class)
查询操作(C-FIND)
移动操作(C-MOVE)
获取操作(C-GET)
四、工作流管理服务类(Workflow Management Service Class)
工作列表操作(C-FIND)
工作流状态管理(N-CREATE、N-SET、N-GET)
工作流结果(N-DELETE)
五、DICOM服务类实例
存储服务类
查询/检索服务类
工作流管理服务类
六、总结
一、概述
DICOM(Digital Imaging and Communications in Medicine)标准不仅定义了数据模型,还包括多种服务类,用于在不同的医疗设备和系统之间传输和管理医学影像数据。DICOM服务类的目标是确保设备与系统间的互操作性,提高影像数据管理的效率和准确性。本文将重点介绍三种主要的DICOM服务类:存储服务类(Storage Service Class)、查询/检索服务类(Query/Retrieve Service Class)和工作流管理服务类(Workflow Management Service Class)。
二、存储服务类(Storage Service Class)
存储服务类是DICOM标准中最基本和最常用的服务类之一,用于在不同的设备和系统之间传输医学影像数据。存储服务类主要包括两个操作:存储(C-STORE)和确认(C-STORE-RSP)。
存储操作(C-STORE)
-
功能
- 存储操作用于将DICOM对象从一个设备发送到另一个设备。通常,发送端设备(Service Class User, SCU)是影像生成设备,如CT机或MRI机,而接收端设备(Service Class Provider, SCP)是存储设备,如PACS(Picture Archiving and Communication System)。
-
请求消息
- 请求消息包含DICOM对象的SOP Instance UID、数据元素和像素数据等。
-
过程
- SCU将包含影像数据和相关元数据的DICOM对象打包成C-STORE请求消息,发送给SCP。
- SCP接收请求消息,解析其中的数据元素,并将影像数据存储到本地数据库或文件系统中。
-
示例代码
1)使用fo-dicom框架的实现 :
using Dicom;
using Dicom.Network;
using System;
using System.IO;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// 创建DicomClient实例
var client = new DicomClient();
// 打开并加载DICOM文件
var dicomFile = DicomFile.Open("path/to/dicom/file.dcm");
// 创建一个C-STORE请求并添加到客户端
client.AddRequest(new DicomCStoreRequest(dicomFile));
// 配置客户端并建立连接
client.NegotiateAsyncOps();
await client.AddRequestAsync(new DicomCStoreRequest(dicomFile));
// 向PACS系统发送请求
await client.SendAsync("PACS_IP", 104, false, "SCU_AE", "PACS_AE");
}
}
2) 使用DCMTK库的实现:
#include "dcmtk/dcmnet/dfindscu.h"
#include "dcmtk/dcmnet/dimse.h"
#include "dcmtk/dcmdata/dcdatset.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include <cstring>
int main()
{
OFCondition status;
T_ASC_Network *net;
T_ASC_Association *assoc;
// 初始化网络
status = ASC_initializeNetwork(NET_REQUESTOR, 0, 30, &net);
if (status.bad()) return 1;
// 请求建立关联
T_ASC_Parameters *params;
ASC_createAssociationParameters(¶ms, ASC_DEFAULTMAXPDU);
ASC_setAPTitles(params, "SCU_AE", "PACS_AE", NULL);
ASC_setTransportLayerType(params, false);
ASC_setPresentationAddresses(params, "SCU_IP", "PACS_IP:104");
status = ASC_requestAssociation(net, params, &assoc);
if (status.bad()) return 1;
// 打开并加载DICOM文件
DcmFileFormat dcmff;
dcmff.loadFile("path/to/dicom/file.dcm");
// 创建C-STORE请求
T_DIMSE_C_StoreRQ req;
T_DIMSE_C_StoreRSP rsp;
std::memset(&req, 0, sizeof(req));
req.MessageID = assoc->nextMsgID++;
strcpy(req.AffectedSOPClassUID, UID_CTImageStorage);
dcmff.getDataset()->findAndGetOFString(DCM_SOPInstanceUID, req.AffectedSOPInstanceUID);
req.Priority = DIMSE_PRIORITY_MEDIUM;
req.DataSetType = DIMSE_DATASET_PRESENT;
// 发送C-STORE请求
status = DIMSE_storeUser(assoc, DIMSE_BLOCKING, 0, &req, NULL, dcmff.getDataset(), NULL, NULL, &rsp, NULL, DIMSE_DATASET_PRESENT);
// 释放关联
ASC_releaseAssociation(assoc);
ASC_dropAssociation(assoc);
ASC_dropNetwork(&net);
return 0;
}
确认操作(C-STORE-RSP)
-
功能
- 确认操作是对存储操作的响应消息。接收端设备(SCP)接收到DICOM对象后,发送确认消息给发送端设备(SCU),表示存储操作是否成功。
-
确认消息
- 确认消息包含操作的状态码,如成功、失败或部分成功等。
-
过程
- SCP在成功存储影像数据后,生成C-STORE-RSP响应消息,并将其发送回给SCU。状态码的解析和处理由SCU完成。
三、查询/检索服务类(Query/Retrieve Service Class)
查询/检索服务类用于在不同的设备和系统之间查询和检索医学影像数据。主要包括三个操作:查询(C-FIND)、移动(C-MOVE)和获取(C-GET)。
查询操作(C-FIND)
-
功能
- 查询操作用于在DICOM数据库中查询特定条件的DICOM对象。查询条件可以包括患者姓名、患者ID、检查日期、影像类型等。
-
请求消息
- 请求消息包含查询条件和返回数据元素的列表。
-
过程
- SCU生成包含查询条件的C-FIND请求消息,并发送给SCP。
- SCP根据查询条件在数据库中查找匹配的DICOM对象,并返回结果列表。
-
示例代码
1)使用fo-dicom框架的实现 :
using Dicom;
using Dicom.Network;
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// 创建DicomClient实例
var client = new DicomClient();
// 创建一个C-FIND请求,查询患者姓名为"John Doe"的影像
var request = new DicomCFindRequest(DicomQueryRetrieveLevel.Study)
{
PatientName = "John Doe"
};
// 处理响应
request.OnResponseReceived += (req, response) =>
{
Console.WriteLine(response.Dataset?.GetString(DicomTag.StudyInstanceUID));
};
// 添加请求到客户端
client.AddRequest(request);
// 向PACS系统发送请求
await client.SendAsync("PACS_IP", 104, false, "SCU_AE", "PACS_AE");
}
}
2) 使用DCMTK库的实现:
#include "dcmtk/dcmnet/dfindscu.h"
int main()
{
DcmFindSCU findscu;
// 设置应用实体标题
findscu.setAETitle("SCU_AE");
findscu.setPeerAETitle("PACS_AE");
findscu.setPeerHostName("PACS_IP");
findscu.setPeerPort(104);
// 创建查询数据集
DcmDataset query;
query.putAndInsertOFStringArray(DCM_PatientName, "John Doe");
// 添加Presentation Context
findscu.addPresentationContext(UID_FINDStudyRootQueryRetrieveInformationModel);
// 发送C-FIND请求
findscu.sendFindRequest("PACS_IP", 104, &query, UID_FINDStudyRootQueryRetrieveInformationModel);
return 0;
}
移动操作(C-MOVE)
-
功能
- 移动操作用于将DICOM对象从一个设备传输到另一个设备。在移动操作中,发送端设备(SCU)发送请求消息给接收端设备(SCP),请求将匹配的DICOM对象传输到指定的第三方设备。
-
请求消息
- 请求消息包含DICOM对象的查询条件和目标设备的AE Title。
-
过程
- SCU生成包含查询条件和目标设备AE Title的C-MOVE请求消息,并发送给SCP。
- SCP根据查询条件查找匹配的DICOM对象,并将其传输到目标设备,同时向SCU发送C-MOVE-RSP确认消息。
4. 代码示例
1)使用fo-dicom框架的实现 :
using Dicom;
using Dicom.Network;
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// 创建DicomClient实例
var client = new DicomClient();
// 创建一个C-MOVE请求,查询患者姓名为"John Doe"的影像
var request = new DicomCMoveRequest("TARGET_AE", DicomQueryRetrieveLevel.Study)
{
PatientName = "John Doe"
};
// 处理响应
request.OnResponseReceived += (req, response) =>
{
Console.WriteLine($"Move response: {response.Status}");
};
// 添加请求到客户端
client.AddRequest(request);
// 向PACS系统发送请求
await client.SendAsync("PACS_IP", 104, false, "SCU_AE", "PACS_AE");
}
}
2) 使用DCMTK库的实现:
#include "dcmtk/dcmnet/dmovescu.h"
int main()
{
DcmMoveSCU movescu;
// 设置应用实体标题
movescu.setAETitle("SCU_AE");
movescu.setPeerAETitle("PACS_AE");
movescu.setPeerHostName("PACS_IP");
movescu.setPeerPort(104);
// 创建查询数据集
DcmDataset query;
query.putAndInsertOFStringArray(DCM_PatientName, "John Doe");
// 添加Presentation Context
movescu.addPresentationContext(UID_MOVEStudyRootQueryRetrieveInformationModel);
// 发送C-MOVE请求,将结果移动到TARGET_AE
movescu.sendMoveRequest("PACS_IP", 104, &query, UID_MOVEStudyRootQueryRetrieveInformationModel, "TARGET_AE");
return 0;
}
获取操作(C-GET)
-
功能
- 获取操作类似于移动操作,但不同的是,获取操作请求将DICOM对象传输回发送端设备(SCU)本身。
-
请求消息
- 请求消息包含DICOM对象的查询条件。
-
过程
- SCU生成包含查询条件的C-GET请求消息,并发送给SCP。
- SCP根据查询条件查找匹配的DICOM对象,并将其传输回SCU,同时发送C-GET-RSP确认消息。
4. 代码示例
1)使用fo-dicom框架的实现 :
using Dicom;
using Dicom.Network;
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// 创建DicomClient实例
var client = new DicomClient();
// 创建一个C-GET请求,查询患者姓名为"John Doe"的影像
var request = new DicomCGetRequest(DicomQueryRetrieveLevel.Study)
{
PatientName = "John Doe"
};
// 处理响应
request.OnResponseReceived += (req, response) =>
{
Console.WriteLine($"Get response: {response.Status}");
};
// 添加请求到客户端
client.AddRequest(request);
// 向PACS系统发送请求
await client.SendAsync("PACS_IP", 104, false, "SCU_AE", "PACS_AE");
}
}
2) 使用DCMTK库的实现:
#include "dcmtk/dcmnet/dgetscu.h"
int main()
{
DcmGetSCU getscu;
// 设置应用实体标题
getscu.setAETitle("SCU_AE");
getscu.setPeerAETitle("PACS_AE");
getscu.setPeerHostName("PACS_IP");
getscu.setPeerPort(104);
// 创建查询数据集
DcmDataset query;
query.putAndInsertOFStringArray(DCM_PatientName, "John Doe");
// 添加Presentation Context
getscu.addPresentationContext(UID_GETStudyRootQueryRetrieveInformationModel);
// 发送C-GET请求
getscu.sendGetRequest("PACS_IP", 104, &query, UID_GETStudyRootQueryRetrieveInformationModel);
return 0;
}
四、工作流管理服务类(Workflow Management Service Class)
工作流管理服务类用于管理医疗影像工作流程,如预约、检查、报告等。主要包括四个操作:工作列表(C-FIND)、工作流状态(N-CREATE、N-SET、N-GET)和工作流结果(N-DELETE)。
工作列表操作(C-FIND)
-
功能
- 工作列表操作用于查询DICOM工作列表,获取待处理的检查任务。工作列表可以包含患者信息、检查类型、预约时间等。
-
请求消息
- 请求消息包含查询条件和返回数据元素的列表。
工作流状态管理(N-CREATE、N-SET、N-GET)
-
N-CREATE
- 功能:用于创建新的工作流实例,表示一个新的检查任务。
- 请求消息:包含新的工作流实例的详细信息,如患者信息、检查类型等。
-
N-SET
- 功能:用于更新工作流实例的状态,如检查开始、检查完成等。
- 请求消息:包含工作流实例的唯一标识符和新的状态信息。
-
N-GET
- 功能:用于获取工作流实例的详细信息。
- 请求消息:包含工作流实例的唯一标识符。
工作流结果(N-DELETE)
-
功能
- 用于删除工作流实例,表示检查任务已完成并从工作列表中移除。
-
请求消息
- 包含工作流实例的唯一标识符。
五、DICOM服务类实例
为了更好地理解DICOM服务类的概念和应用场景,我们以一个具体的实例进行说明。假设我们有一个PACS系统和一个影像工作站,需实现以下操作:
存储服务类
-
操作描述
- 影像工作站生成一张新的CT图像,并将其存储到PACS系统中。
- 影像工作站发送C-STORE请求消息,将CT图像对象传输到PACS系统。
- PACS系统接收到CT图像对象后,发送C-STORE-RSP确认消息给影像工作站,表示存储操作成功。
-
过程与技术
- 影像工作站使用图像采集设备(如CT机)生成DICOM对象,包含影像数据和元数据。
- DICOM对象通过网络传输协议发送至PACS系统,PACS系统解析并存储图像。
- PACS系统将操作结果通过C-STORE-RSP消息反馈给影像工作站。
查询/检索服务类
-
操作描述
- 医生在影像工作站上查询某个患者的所有CT影像。
- 影像工作站发送C-FIND请求消息,查询PACS系统中的CT影像对象。
- PACS系统返回匹配的CT影像对象列表给影像工作站。
- 医生选择其中一张CT影像,并请求将其传输到影像工作站进行查看。
- 影像工作站发送C-MOVE请求消息,请求PACS系统将CT影像对象传输到影像工作站。
- PACS系统将CT影像对象传输到影像工作站,并发送C-MOVE-RSP确认消息。
-
过程与技术
- 影像工作站通过网络协议与PACS系统建立连接。
- 影像工作站发送C-FIND请求,PACS系统查询数据库并返回匹配结果。
- 影像工作站选择需要的影像,发送C-MOVE请求,PACS系统将影像传输至影像工作站。
- PACS系统确认传输成功并发送C-MOVE-RSP消息。
工作流管理服务类
-
操作描述
- 放射科接收到一位新患者的CT检查预约。
- PACS系统发送N-CREATE请求消息,创建新的工作流实例,表示一个新的CT检查任务。
- 检查开始时,影像工作站发送N-SET请求消息,更新工作流实例的状态为“检查开始”。
- 检查完成后,影像工作站发送N-SET请求消息,更新工作流实例的状态为“检查完成”。
- 医生查看和报告完毕后,PACS系统发送N-DELETE请求消息,删除工作流实例,表示检查任务已完成并从工作列表中移除。
-
过程与技术
- PACS系统接受预约信息,生成新的工作流实例并发送N-CREATE请求。
- 在检查流程中,影像工作站通过N-SET消息更新工作流状态。
- 检查完成后,工作流状态再次更新为“检查完成”。
- 医生完成报告后,PACS系统通过N-DELETE消息删除工作流实例。
六、总结
DICOM服务类定义了多种操作,用于在不同的医疗设备和系统之间传输和管理医学影像数据。通过理解存储服务类、查询/检索服务类和工作流管理服务类的概念、应用场景和操作原理,我们可以更好地实现医学影像数据的互操作性和工作流管理。具体实例有助于我们掌握这些服务类在实际应用中的操作和流程,提高医疗影像数据管理的效率和准确性。
通过深入了解DICOM服务类的各个方面,我们能够更好地在实际医疗环境中应用这些标准和技术,以提高医疗影像数据的传输和管理效率,增强不同设备和系统间的互操作性,从而更好地服务于医疗实践和病人护理。