使用 pydicom 添加新的 DICOM 标签

Adding new DICOM tag with pydicom

我正在尝试使用 freesurfer 的 dcm2nii 实用程序将大量 DTI 西门子 DICOM 转换为 NifTi,但在某些文件上失败,因为它们缺少 DiffusionGradientDirection tag (0x19,0x100E),这是生成.bvec.bval 个文件。并不是标签没有值,它们似乎根本不存在。

ds[0x19,0x100E] Traceback (most recent call last): File "", line 1, in File "/space/jazz/1/users/gwarner/anaconda/lib/python2.7/site-packages/pydicom-0.9.9-py2.7.egg/dicom/dataset.py", line 277, in getitem data_elem = dict.getitem(self, tag) KeyError: (0019, 100e)

我尝试添加它但出现以下错误:

ds[0x19,0x100E].value = 'yes' Traceback (most recent call last): File "", line 1, in File "/space/jazz/1/users/gwarner/anaconda/lib/python2.7/site-packages/pydicom-0.9.9-py2.7.egg/dicom/dataset.py", line 277, in getitem data_elem = dict.getitem(self, tag) KeyError: (0019, 100e)

有什么方法可以手动插入这个标签吗?

我需要在这里使用我的 crystal 球来回答问题,因为我无法访问您的 DICOM 数据集,但我敢打赌这对您来说是失败的,因为您没有好的了解 Privates Tags 在 DICOM 中的工作原理。

我找到了一个总结情况的写得很好的页面(仅在 web.archive 中可用)。总之,您需要仔细检查 dcmdump and/or gdcmdump 之类的输出来指导您。

让我们使用著名的 GDCMData 示例文件之一综合一下这里发生的事情(但它对您来说应该是一样的)。

$ gdcmdump SIEMENS_CSA2.dcm | grep 0019
(0019,0010) LO [SIEMENS MR HEADER ]                               # 18,1 Private Creator
(0019,1008) CS [IMAGE NUM 4 ]                                     # 12,1 CSA Image Header Type
(0019,1009) LO [1.0 ]                                             # 4,1 CSA Image Header Version ??
(0019,100b) DS [10632.5 ]                                         # 8,1 SliceMeasurementDuration
(0019,100f) SH [Fast]                                             # 4,1 GradientMode
(0019,1011) SH [No]                                               # 2,1 FlowCompensation
(0019,1012) SL 0[=10=]\-2134                                          # 12,3 TablePositionOrigin
(0019,1013) SL 0[=10=]\-2134                                          # 12,3 ImaAbsTablePosition
(0019,1014) IS [0[=10=][=10=] ]                                           # 6,3 ImaRelTablePosition
(0019,1015) FD -162.438\-61.40924.003                          # 24,3 SlicePosition_PCS
(0019,1017) DS [0.642857]                                         # 8,1 SliceResolution
(0019,1018) IS [7800]                                             # 4,1 RealDwellTime

正如你在上面看到的那样,gdcmdump 可以看出 0019,1018 是 RealDwellTime

如果我们天真地删除私人创作者标签现在会发生什么:

$ gdcmanon --dumb --remove 0019,0010 SIEMENS_CSA2.dcm /tmp/hack.dcm
$ gdcmdump /tmp/hack.dcm | grep 0019
(0019,1008) CS [IMAGE NUM 4 ]                                     # 12,? (1)  Private Element With Empty Private Creator
(0019,1009) LO [1.0 ]                                             # 4,? (1)  Private Element With Empty Private Creator
(0019,100b) DS [10632.5 ]                                         # 8,? (1)  Private Element With Empty Private Creator
(0019,100f) SH [Fast]                                             # 4,? (1)  Private Element With Empty Private Creator
(0019,1011) SH [No]                                               # 2,? (1)  Private Element With Empty Private Creator
(0019,1012) SL 0[=11=]\-2134                                          # 12,? (3)  Private Element With Empty Private Creator
(0019,1013) SL 0[=11=]\-2134                                          # 12,? (3)  Private Element With Empty Private Creator
(0019,1014) IS [0[=11=][=11=] ]                                           # 6,? (3)  Private Element With Empty Private Creator
(0019,1015) FD -162.438\-61.40924.003                          # 24,? (3)  Private Element With Empty Private Creator
(0019,1017) DS [0.642857]                                         # 8,? (1)  Private Element With Empty Private Creator
(0019,1018) IS [7800]                                             # 4,? (1)  Private Element With Empty Private Creator

突然我们遇到了奇怪的情况,DICOM 属性 0019,1018 仍然存在于数据集中,但是由于 'some' 原因,gdcmdump 无法告诉我们这是 'RealDwellTime'。

我猜这对您来说也是同样的问题,您缺少用于私有标签间接访问的密钥 (SIEMENS MR HEADER)。


附带说明一下,您是否检查过扩散信息没有直接存储在 CSA 中 header,例如:

$ gdcmdump --csa my_input.dcm | grep -i diffusion

在那种情况下,我会向 pydicom 报告错误,以便他们也解析此 DICOM 属性以检索扩散信息。

要将pydicom中的新私有数据元素添加到数据集ds,可以使用add_new方法:

ds.add_new(tag, VR, value)

对于这种情况,在 pydicom 的 _private_dict.py 文件中查找私有标签(源自 gdcm 的私有标签信息):

 'SIEMENS MR HEADER': {
    ...
    '0019xx0e': ('FD', '3', 'DiffusionGradientDirection', ''),

这是一种重复组标记,其中 xx 可以更改以允许同一类型的多个数据元素。这里 FD 是双浮点数,3 是多重性(预期三个值)。

所以在这种情况下,要添加您需要的数据元素应该类似于:

ds.add_new(0x19100e, 'FD', [0,1,0]) # I have no idea what this last vector should actually be

然而,正如 malat 指出的那样,还需要有一个私人创建者标签来引入块,文件才能成为有效的 DICOM。如果它还不存在,您可能还必须添加它。由于您正在将文件转换为另一种格式,也许您不关心仅添加单个标签是否有效。

添加数据元素后,您可以像在原始问题中那样使用 ds[0x19100e].value = ... 更改值。

顺便说一句,标准词典中的关键字不需要 add_new;对于那些可以直接按名称设置项目的人,例如ds.OtherPatientIDs='test',即使它还不存在于数据集中。