java dcm4che findscu实现workList通讯——客户端SCU

全网实现workList服务的,要么是基于C++的DCMTK、要么是基于C#的fo-dicom。想用dcm4che实现 找了好几个月都没有一个例子。无奈只能通过DCMTK和fo-dicom 实现方式并查看dcm4che源码自己实现了。经过不懈的努力总算是实现了并实际跟设备测试成功!首先得先了解 DICOM worklist工作原理?一、关于Worklist在RIS与PACS的系统集成中。Wordlist的连接bai为其主要工作之一。Wordlist成像设备工作列表,它是DICOM协议中众多服务类别.
摘要由CSDN通过智能技术生成

全网实现workList服务的,要么是基于C++的DCMTK、要么是基于C#的fo-dicom。想用dcm4che实现 找了好几个月都没有一个例子。无奈只能通过DCMTK和fo-dicom 实现方式并查看dcm4che源码自己实现了。经过不懈的努力总算是实现了并实际跟设备测试成功!

首先得先了解 DICOM worklist工作原理?

一、关于Worklist

在RIS与PACS的系统集成中。Wordlist的连接bai为其主要工作之一。Wordlist成像设备工作列表,它是DICOM协议中众多服务类别中的一个.它的功能是实现设备操作台与登记台之间的通讯,完成成像设备和信息系统的集成.称为BASIC WORKLIST MANAGEMENT SERVICE(简称Worklist)。

二、DICOM标准中与Worklist相关的一些基本概念

配置影像检查设备(Modality)的Worklist首先要阅读该设备的“DICOM 一致性声明(DICOM Conformance Statement)”中关于Worklist的部分,了解设备对Worklist的支持程度。而熟悉以下基本概念则有助于阅读DICOM Conformance Statement:

1、VR(Value Representation):描述了数据元素的种类(字符串、数字、日期等)以及这些值的格式。在DICOM标准第五部分Data Structures and Encoding的第25页中列出了所有的VR。

2、Data Set(数据集):一个数据集表示了一个DICOM对象,它进一步由Data Element(数据元素)组成。而数据元素包括了tag(唯一的)、值的长度以及值。数据元素中可能包含VR。

3、 数据元素类型:一个数据元素是否在一个数据集中出现,取决于该数据元素的类型。

4、 AE Title:AE Title(Application Entity Title)是配置影像检查设备DICOM服务(Worklist、Storage、Print等)必不可少的参数之一。对于某一台影像检查设备,其各个DICOM服务可以对应不同的AE Title,当然这些DICOM服务也可以对应同一个AE Title。AE Title是一个字符串,但是这个字符串在我们要配置的RIS/PACS系统的网络中必须是唯一的。因此,AE Title是这个网络中某一个(或几个)DICOM服务的唯一标识。

三、DICOM的Worklist实现的功能

fz2841585:从RIS或者其他系统下载病人信息,以免重复登记。

0753zhongwei:Worklist只是一个传输协议,DICOM的Worklist其实就是C-FIND服务,有点类似于Query/Retrieve,SCU在C-FIND命令集后面加上一些查询字段,SCP把查询结果放在C-FIND-RSP后面返回去。

tks1000:在CT或MR等工作站上,如果没有Worklist功能,新检查一个病人的时候,要输入病人全部的基本信息,这样比较麻烦,而且容易出错。有了WorkList功能后,可以直接从服务器上读取病人的基本信息,不用输入,而且不易出错。实质上还是C-FIND,不过需要MPPS等的支持。

chaoran898:DICOM的MWL是一种接口协议,至于怎样查数据,那是coding实现的事情,MWL只负责把找到的数据按DICOM标准传出去。

xiaoyilong19:我做了多台设备的Worklist,深有体会:如果设备厂家不同的话,Worklist服务端程序就要调试一番,才能让返回的数据在对方设备工作站上显示出来,否则就是出现各种情况。乱码还比较简单处理,就是怕对方什么应答都没有。实际上就是,请求,返回请求,和cs服务架构一样。

四、Worklist在Pacs中的作用与的工作原理

图源网络

五、 基本设计概念和处理流程

xuyuansheng:正常的流程是,病人在HIS上注册,经hl7消息传至RIS,RIS上便有了病人的登记信息。做检查时,成像设备通过DICOM Worklist来从RIS上取得需做检查的病人列表,选择后做检查。检查完成后,图像便可以传到PACS中进行存储。在这个过程中,病人信息仅在HIS端输入一遍,但它流经RIS,Modality以及PACS。可以节省时间,减少错误,规范流程,互联互通,形成数据共享。理想的情况下,让医生专注于检查及诊断,而缩短的时间,也会提高病人的满意度。

六、总结
看到这里后大概知道 workList 其实就是一个客户端(SCU)发起C-Find请求 服务端(SCP)将这些结果按照DICOM协议返回对应的字段组合即可

接下来就该查看DCM4CHE源码了

我们现在知道了workList 其实就是C-Find请求 我们就在dcm4che源码里找关于c-find的一切内容了!

原来dcm4che源码中dcm4che-tool 有个dcm4che-tool-findscu

在这里插入图片描述
在这里插入图片描述
很是惊喜 总算找到个入口了
在这里插入图片描述
甚至还有命令示例,NICE!
例子:

findscu -c DCMQRSCP@localhost:11112 -m PatientName=Doe^John -m
StudyDate=20110510- -m ModalitiesInStudy=CT

github上对各个命令都有解释,这里简单解释一下这个例子

-c 代表远程连接

DCMQRSCP是指dcm4che服务的AETitle

localhost是指dcm4che服务的ip地址

11112是指dcm4che服务的端口

-m PatientName=Doe^John 代表查询患者姓名是Doe^John

-m StudyDate=20110510 代表查询患者检查时间是20110510

-m ModalitiesInStudy=CT 代表查询患者的模态是CT

命令也支持xml文件查询和结果导出xml
在这里插入图片描述
甚至dcm4chee 文件里有执行findscu 命令脚本!是不是感觉离成功近了一大步~~
先试试脚本命令
(本地局域网已经部署好了 dcm4chee-web 可以直接把它当作worklist scp)
在这里插入图片描述
确实可以建立了通讯并且可以查询 那接下来就从 FindSCU.java源码下功夫了

充分阅读源码后 将源码进行改造

直击源码里的main 方法

 public static void main(String[] args) {
   
        try {
   
            CommandLine cl = parseComandLine(args);//解析命令
            FindSCU main = new FindSCU();
            CLIUtils.configureConnect(main.remote, main.rq, cl); 设置连接ip和端口 
            CLIUtils.configureBind(main.conn, main.ae, cl);
            CLIUtils.configure(main.conn, cl);
            main.remote.setTlsProtocols(main.conn.getTlsProtocols());// 设置Tls协议
            main.remote.setTlsCipherSuites(main.conn.getTlsCipherSuites());
            configureServiceClass(main, cl);
            configureKeys(main, cl);
            configureOutput(main, cl);// 设置检索级别
            configureCancel(main, cl);// 配置 --cancel
            main.setPriority(CLIUtils.priorityOf(cl));
            ExecutorService executorService =
                    Executors.newSingleThreadExecutor();
            ScheduledExecutorService scheduledExecutorService =
                    Executors.newSingleThreadScheduledExecutor();
            main.device.setExecutor(executorService);
            main.device.setScheduledExecutor(scheduledExecutorService);
            try {
   
                main.open();// 打开链接
                List<String> argList = cl.getArgList();
                if (argList.isEmpty())
                    main.query();// 查询 这里是重点
                else
                    for (String arg : argList)
                        main.query(new File(arg));
            } finally {
   
                main.close();
                executorService.shutdown();
                scheduledExecutorService.shutdown();
            }
       } catch (ParseException e) {
   
            System.err.println("findscu: " + e.getMessage());
            System.err.println(rb.getString("try"));
            System.exit(2);
        } catch (Exception e) {
   
            System.err.println("findscu: " + e.getMessage());
            e.printStackTrace();
            System.exit(2);
        }
    }

具体看query 方法

    public void query( DimseRSPHandler rspHandler) throws IOException, InterruptedException {
   
        query(keys, rspHandler);
    }
    
    private void query(Attributes keys, DimseRSPHandler rspHandler) throws IOException, InterruptedException {
   
        as.cfind(model.cuid, priority, keys, null, rspHandler);
    }

主要看懂源码的这两个地方 大概实现findscu 就有思路了

需要的maven 包

 <dependency>
            <groupId>org.dcm4che</groupId>
            
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 31
    评论
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值