3d Slicer-DICOM模块之Query/Retrieve功能介绍
Posted inter_peng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3d Slicer-DICOM模块之Query/Retrieve功能介绍相关的知识,希望对你有一定的参考价值。
本文由Markdown语法编辑器编辑完成。
1. DICOM模块
3d Slicer作为医学影像的开源处理软件,当然离不开医学影像数据。
DICOM模块,就是专门负责DICOM影像的查找,获取,发送和接收的模块。
官方文档中关于DICOM的描述,见链接: https://slicer.readthedocs.io/en/latest/user_guide/modules/dicom.html
上述图像介绍了,3d Slicer加载医学影像的流程。
3d Slicer既支持加载DICOM影像数据,也支持加载非dcm数据,如NRRD, STL, JSON等格式的数据。
除了本地加载影像文件外,DICOM协议支持通过网络传输影像。也就是如上图中,红色框内的: DICOM query/retrieve。
2. Query/Retrieve功能介绍
Query/Retrieve功能,对应的是dicom协议中的findscu和movescu/getscu.
功能 | dcmtk指令 |
---|---|
Query | findscu |
Retrieve | movescu/getscu |
在3d Slicer的DICOM页面中,有一个项目是: DICOM networking, 就是提供通过网络来进行DICOM影像传输的功能入口。
点击: "Query and retrieve"按钮,即可以进入如下的弹出页面。
页面中显示了,3d Slicer默认的AE Title为: “CTKSTORE”。
下面则是配置需要连接的PACS服务器的信息。
由于我已经在本地用dcm4chee搭建了一个PACS服务器。PACS服务器的AE Title是: DCM4CHEE,
Address是:192.168.109.83,Port是11112,且支持通过CGET的方式获取数据。
右侧的红框 Search Options, 就是通过一些已知的Patient/Study/Series的信息,来从PACS的服务器检索相关的数据。检索选择框下方的两列,看起来比较明显。一列是日期,另一列是Modality。
但是上方的 Name/Study/Series/ID, 就不是很明显。不知道应该输入什么信息,也不知道应该以什么样的格式来输入。
在Google上检索了很多关于3d Slicer的query/retrieve的文章,但都是关于如何利用下面的日期和Modality来query数据的,对于上面的Name/Study/Series/ID, 却没有介绍。
最后实在没有办法了。只能通过查询3d Slicer的源码来寻找有价值的信息了。
由于3d Slicer是一个持续了20多年的开源项目,因此代码量是相当庞大的。如何在如此庞大的代码量前面迅速地定位相关代码,也没有更好的办法。我只能是通过将代码加载在Visual Studio Code里面,然后利用编辑器自带的搜索功能,来搜索了。
我用的关键字是搜索框上方的"Search Options"。首先是在源码里面搜索,结果没有搜到任何信息。后来想到,3d Slicer在编译的过程中,同时还下载和编译了十几个项目的代码。因此,我又在3d Slicer bulid的目录下查找,结果真的找到了。
最后定位到的文件是位于3d Slicer的编译目录: Slicer-SuperBuild-Debug下的:
CTK/Libs/DICOM/Core/ctkDICOMQuery.cpp的函数: ctkDICOMQuery:query()中的Line 324 ~ 380.
/* Now, for all keys that the user provided for filtering on STUDY level,
* overwrite empty keys with value. For now, only Patient's Name, Patient ID,
* Study Description, Modalities in Study, and Study Date are used.
*/
QString seriesDescription;
foreach( QString key, d->Filters.keys() )
{
if ( key == QString("Name") && !d->Filters[key].toString().isEmpty())
{
// make the filter a wildcard in dicom style
d->Query->putAndInsertString( DCM_PatientName,
(QString("*") + d->Filters[key].toString() + QString("*")).toLatin1().data());
}
else if ( key == QString("Study") && !d->Filters[key].toString().isEmpty())
{
// make the filter a wildcard in dicom style
d->Query->putAndInsertString( DCM_StudyDescription,
(QString("*") + d->Filters[key].toString() + QString("*")).toLatin1().data());
}
else if ( key == QString("ID") && !d->Filters[key].toString().isEmpty())
{
// make the filter a wildcard in dicom style
d->Query->putAndInsertString( DCM_PatientID,
(QString("*") + d->Filters[key].toString() + QString("*")).toLatin1().data());
}
else if ( key == QString("Modalities") && !d->Filters[key].toString().isEmpty())
{
// make the filter be an "OR" of modalities using backslash (dicom-style)
QString modalitySearch("");
foreach (const QString& modality, d->Filters[key].toStringList())
{
modalitySearch += modality + QString("\\\\");
}
modalitySearch.chop(1); // remove final backslash
logger.debug("modalityInStudySearch " + modalitySearch);
d->Query->putAndInsertString( DCM_ModalitiesInStudy, modalitySearch.toLatin1().data() );
}
// Rememer Series Description for later series query if we go through the keys now
else if ( key == QString("Series") && !d->Filters[key].toString().isEmpty())
{
// make the filter a wildcard in dicom style
seriesDescription = "*" + d->Filters[key].toString() + "*";
}
else
{
logger.debug("Ignoring unknown search key: " + key);
}
}
if ( d->Filters.keys().contains("StartDate") && d->Filters.keys().contains("EndDate") )
{
QString dateRange = d->Filters["StartDate"].toString() +
QString("-") +
d->Filters["EndDate"].toString();
d->Query->putAndInsertString ( DCM_StudyDate, dateRange.toLatin1().data() );
logger.debug("Query on study date " + dateRange);
}
正如这段代码的注释部分所描述的,3d Slicer的Search Options,目前的对应关系是:
Search Options | DICOM TAG |
---|---|
Name | Patient’s Name |
Study | Study Description |
Series | Series Description |
ID | Patient ID |
Date | Study Date |
Modality | Modalities in Study |
根据以上的对应关系,便可以在Search Options的对应的Tab页输入相应的查询条件,来进行数据的检索。
完。
以上是关于3d Slicer-DICOM模块之Query/Retrieve功能介绍的主要内容,如果未能解决你的问题,请参考以下文章
妙味课堂实战功能开发视频教程 3D翻转焦点图/瀑布流/拖拽购物车/模块化开发等实战教程
Irrlicht 3D Engine 笔记系列 之 教程5- User Interface