您的位置:首页 > 其它

DICOM医学图像处理:利用fo-dicom发送C-Find查询Worklist

2014-09-01 21:55 597 查看

背景:

如上一篇专栏博文所描述,Worklist可以看做是PACS系统、MODALITY设备和RIS系统之间的信息交换。从RIS系统到MODALITY通过Worklist可以提供诸如患者个人信息(姓名、年龄、生日等)和其他管理数据,以及提供关于成像过程和产生图像相关的一个唯一UID等信息。基本的结构如下图:




(具体来源不清楚了,非本人原创)

问题提出:

上一次利用DCMTK开源库顺利的模拟了“发送C-Find请求,查询worklist信息”的整个过程,通过利用DCMTK开源库提供的wlmscpfs.exe和findscu.exe工具包,使得模拟过程简单明了。此次希望通过fo-dicom(C#版的DCMTK)库来模拟该过程。

解决方案:

1)前提条件:

为了使得该模拟过程与上一篇博文的过程具有可比性,此次只利用fo-dicom库来构建C#版本的发送C-Find请求的过程,worklist服务端依然使用DCMTK提供的工具包wlmscpfs.exe。

2)利用fo-dicom发送C-Find请求:

具体代码如下,



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Dicom;
using Dicom.Network;
using Dicom.Log;

namespace FindSCU1
{

    class Program
    {

        static void Main(string[] args)
        {

            string id = "123456";
            var cfind = DicomCFindRequest.CreateWorklistQuery(patientId: id);
            cfind.OnResponseReceived = (DicomCFindRequest rq, DicomCFindResponse rp) =>
            {
                Console.WriteLine("********Patient Name is  {0}**********", rp.Dataset.Get<string>(DicomTag.PatientName));
             };
            var client = new DicomClient();
            client.AddRequest(cfind);
            client.Send("127.0.0.1", 104, false, "SCU-LargeV", "OFFIS");
            Console.Read();
        }
    }
}


3)实际测试:

利用wlmscpfs.exe开启worklist服务,输入如下指令:

>wlmscpfs.exe 104 –d –dfp d:\DcmWorklist\wlistdb

显示效果如下:





表示worklist服务端已经顺利启动……

找到步骤2)中生成的可执行程序FindSCU1.exe,双击直接运行,此时服务端和客户端的结果如下:





(客户端)

(服务端)

4)错误调试:

只是简单的发送了一次以PatientID为目标的worklist查询服务,代码总共没有几行的,为什么会出现异常呢?根据上述客户端的异常提示,通过单步调试,定位到首次抛出异常的“事故点”:DicomDatasetReaderObserver.cs的OnElement函数中,该函数是从DicomReader.cs的ParseDataset函数中跳转过来的。截取OnElement函数的代码,





发现该函数内部,由于无法识别VR类型为SQ的字段,因此而抛出了throw new DicomDataException("Unhandled VR in DICOM parser observer: {0}", vr.Code)异常。

仔细回想一下我们的代码在哪个位置会出现SQ类型的字段呢?只有在CreateWorklistQuery函数中可能添加过SQ类型的字段,进入到DicomCFindRequest.cs中的CreateWorklistQuery函数内部,发现的确有如下代码:

dimse.Dataset.Add(new DicomSequence(DicomTag.ReferencedStudySequence));

为了证实我们的猜测,此处直接将该行代码注释掉,然后在fo-dicom源码工程中编译DICOM工程,重新生成Dicom.dll程序集。重新编译运行我们的测试工程FinSCU1.exe。服务端和客户端能够顺利运行,





总结验证:

修改fo-dicom库源码毕竟不是常规方法,在网络上搜索发现Github上有人遇到过类似的情形(https://github.com/rcd/fo-dicom/issues/62#issuecomment-46248073,如下图)最终也是修改fo-dicom源代码解决的。所以猜测可能是fo-dicom源代码中的部分逻辑还没有完善,还存在着些许漏洞。









为了验证是否是由于dimse.Dataset.Add(new DicomSequence(DicomTag.ReferencedStudySequence));添加了SQ格式的字段而导致的服务端错误,我们利用上次创建wlistqry.wl查询文件的DCMTK工程,向其中写入SQ格式的(0008,1110)DCM_ReferencedStudySequence字段,代码如下:

dataset->insertEmptyElement(DCM_ReferencedStudySequence);

然后利用findscu.exe 来进行查询操作,查看worklist服务端程序wlmscpfs是否正常,验证结果图如下:




由此证明,根本原因并不是由于WorklistQuery中插入了SQ格式的字段所引起的,在此仅仅标记一下,等待后续的继续排查和验证。



(未完待续……)



作者:zssure@163.com

时间:2014-09-01
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: