概要
在用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.
我們來一個簡單有查詢定義:
// 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語句就是:
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’ |
以上例子就相當於是
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/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

