使用 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'
,即使它还不存在于数据集中。
我正在尝试使用 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'
,即使它还不存在于数据集中。