DICOM标准中关于C-Find,运用StudyTime进行查找时无法查找到数据的问题

本文由Markdown语法编辑器编辑完成。

1. 问题提出:

近日在运用C-Find从PACS服务器拉取数据的时候,发现同样的代码,在拉取跨越午夜的数据时,出现了拉取不到数据的问题。举个例子:
比如医院在2019-06-13 23:00:00,新产生了一个检查数据。而我通过C-Find要拉取数据时,C-Find的指令如下:
./bin/dcmtk3.6.3/findscu --study -aet TEST -aec DCM4CHEE -v 127.0.0.1 11112 -k 08,52=STUDY -k StudyInstanceUID= -k StudyDate=20190613-20190614 -k StudyTime=180000-080000.
根据C-Find的指令,释义应该是:
查询STUDY级别,2019-06-13 18:00:00 ~ 2019-06-14 08:00:00这14个小时范围内的数据。那么23:00:00是在这个查询时间范围内的,应该能够查询到这个检查。
但是,实际上,在terminal中执行这条指令后,却并没有查询到期望的记录。

2. dicom标准说明:

当遇到类似的问题时,最好的办法当然是去读dicom的相关标准了。因此,通过在网上用相应的关键词搜索,得到了关于findscu,在运用StudyDate和StudyTime参数进行查找时的一些说明,具体的网页链接如下所示:
http://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_C.2.2.2.5.html
摘录一些关键的内容如下:

C.2.2.2.5.2 Range Matching of Attributes of VT of TM
All comparison specified in the following shall be based on a direct comparison of times within a day. “Prior” includes all times starting from midnight of the same day to the specified time. “Subsequent” includes all times starting with the specified time until any time prior to midnight of the following day. Range matching crossing midnight is not supported.
No offset from Universal Coordinated Time is permitted in the TM VR values. If Timezone Offset From UTC (0008,0201) is present in the query identifier, the specified time values and the definition of midnight are in the specified timezone.
上文中加粗的部分是重点,意思是:以下定义的所有的时间的比较,应该是基于一天内的时间比较。时间范围如果跨越午夜是不被支持的。

当读完该内容后,就知道为什么跨越午夜是查找不到图像的。
但是,如果在实际运行环境中,必然会出现跨越午夜的情况,应该怎么办呢?那就是,人为地将时间拆成两个时间段。
比如:2019-06-13 18:00:00 ~ 2019-06-14 08:00:00,我可以将这个区间区分为两个阶段:
阶段一:2019-06-13 18:00:00~23:59:59;
阶段二:2019-06-14 00:00:00~08:00:00.

如果查询的时间不仅跨越午夜,还跨一个整天以上,则可以将时间拆分为三段来处理:
比如:2019-06-11 18:00:00 ~ 2019-06-14 08:00:00,可以拆分为:
阶段一:2019-06-11 18:00:00~23:59:59
阶段二:2019-06-12 ~ 2019-06-13 (这是两个整天,不需要studyTime)
阶段三:2019-06-14 00:00:00~08:00:00

3. 解决方案:


from datetime import timedelta

def days_between(d1, d2):
    """
    :param 年-月-日 d1
    :param 年-月-日 d2
    return: 返回两个天数的差异 type int
    """
    d1 = datetime.strptime(d1, "%Y-%m-%d")
    d2 = datetime.strptime(d2, "%Y-%m-%d")
    return abs((d2 - d1).days)

# 注:findscu()是一个封装好的函数,主要是用于实现dicom的cfind指令。由于这里是查询检查,因此在findscu时,query_level需要设置为"08,52=STUDY", 查询后返回的数据模型,也是"--study"级别.因此实际运行时的指令为:./dcmtk3.6.3/findscu --study -aet TEST -aec DCM4CHEE -v 127.0.0.1 11112 -k 08,52=STUDY -k StudyInstanceUID=  -k StudyDate=20190613-20190614 -k StudyTime=180000-080000.
# 关于findscu的详细参数,见链接:https://support.dcmtk.org/docs/findscu.html
def findStudyUIDByDateTime(start, end):
	#start, end为传入的查询区间的时间值.
	
	extract_keys = ['StudyInstanceUID']	
	    results = list()
	    if int(start.strftime('%Y%m%d')) == int(end.strftime('%Y%m%d')):
	        results = findscu(
	            {
	                'StudyInstanceUID': '',
	                'StudyDate':
	                    start.strftime('%Y%m%d') + '-' + end.strftime('%Y%m%d'),
	                'StudyTime':
	                    start.strftime('%H%M%S') + '-' + end.strftime('%H%M%S'),
	            }, extract_keys)
	
	    elif int(start.strftime('%Y%m%d')) < int(end.strftime('%Y%m%d')):
	        studyTime_before_midnight = start.strftime('%H%M%S') + '-' + '235959'
	        studyTime_after_midnight = '000000' + '-' + end.strftime('%H%M%S')
	        results_yesterday = findscu(
	            {
	                'StudyInstanceUID': '',
	                'StudyDate': start.strftime('%Y%m%d'),
	                'StudyTime': studyTime_before_midnight,
	            }, extract_keys)
	
	        results_today = findscu(
	            {
	                'StudyInstanceUID': '',
	                'StudyDate': end.strftime('%Y%m%d'),
	                'StudyTime': studyTime_after_midnight,
	            }, extract_keys)
	
	        date_interval = days_between(start.strftime('%Y-%m-%d'), end.strftime('%Y-%m-%d')) - 1
	        results_interval = list()
	        if date_interval > 0:
	            interval_start = start + timedelta(days=1)
	            interval_end = end - timedelta(days=1)
	            results_interval = findscu(
	                {
	                    'StudyInstanceUID': '',
	                    'StudyDate': interval_start.strftime('%Y%m%d') + '-' +
	                                 interval_end.strftime('%Y%m%d'),
	                }, extract_keys)
	
	        results = results_yesterday + results_today + results_interval
	
	    studyInfo_list = \
	        [studyInfo(study_uid=result['StudyInstanceUID'])for result in results]

参考链接:

DICOM标准:Query/Retrieve Service Class: Range Matching.
http://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_C.2.2.2.5.html
Findscu指令:
https://support.dcmtk.org/docs/findscu.html

你可能感兴趣的:(DICOM)