I have not been able to find an easy way to do this by reading the documentation or skimming the source code.
To give a concrete example, I'd like to convert this example from the docs
(0008, 0012) Instance Creation Date DA: '20030903'
(0008, 0013) Instance Creation Time TM: '150031'
(0008, 0016) SOP Class UID UI: RT Plan Storage
(0008, 0018) SOP Instance UID UI: 1.2.777.777.77.7.7777.7777.20030903150023
(0008, 0020) Study Date DA: '20030716'
(0008, 0030) Study Time TM: '153557'
(0008, 0050) Accession Number SH: ''
(0008, 0060) Modality CS: 'RTPLAN'
to a dictionary something like this:
{'Instance Creation Date': '20030903', ...}
One solution looks something like this:
dicom_file = dicom.read_file("rtplan.dcm")
d = dict()
for k in dicom_file.__dir__():
if not k.startswith("__"):
try:
d[k] = dicom_file.data_element(k).value
except:
pass
However, that's not particularly elegant.
Your example won't work for sequences.
def dictify(ds):
"""Turn a pydicom Dataset into a dict with keys derived from the Element tags.
Parameters
----------
ds : pydicom.dataset.Dataset
The Dataset to dictify
Returns
-------
output : dict
"""
output = dict()
for elem in ds:
if elem.VR != 'SQ':
output[elem.tag] = elem.value
else:
output[elem.tag] = [dictify(item) for item in elem]
return output
You could also use elem.name or elem.keyword instead of elem.tag, however these may not be unique if there are private data elements.
@scaramallion Thank you very much for the help.
elem.keyword yields an AttributeError on my data. However, using elem.name instead works very well. I'm not clear on why.
That said, I think that a function like the one you have written would make a very nice addition to the library.
I've used the following to convert a dataset to a dict (for storing as JSON) if it's any help. The repr call to populate the elements feels like hack though.
def dicom_dataset_to_dict(dicom_header):
dicom_dict = {}
repr(dicom_header)
for dicom_value in dicom_header.values():
if dicom_value.tag == (0x7fe0, 0x0010):
# discard pixel data
continue
if type(dicom_value.value) == dicom.dataset.Dataset:
dicom_dict[dicom_value.tag] = dicom_dataset_to_dict(dicom_value.value)
else:
v = _convert_value(dicom_value.value)
dicom_dict[dicom_value.tag] = v
return dicom_dict
def _sanitise_unicode(s):
return s.replace(u"\u0000", "").strip()
def _convert_value(v):
t = type(v)
if t in (list, int, float):
cv = v
elif t == str:
cv = _sanitise_unicode(v)
elif t == bytes:
s = v.decode('ascii', 'replace')
cv = _sanitise_unicode(s)
elif t == dicom.valuerep.DSfloat:
cv = float(v)
elif t == dicom.valuerep.IS:
cv = int(v)
elif t == dicom.valuerep.PersonName3:
cv = str(v)
else:
cv = repr(v)
return cv
Ah yeah, sorry, keyword is in 1.0.0a1, not 0.9.9 which you seem to be using.
Thinking about it a bit more, you're better off using elem.tag as this is guaranteed to be unique. For private elements the name/keyword is unlikely to be unique. I've updated my solution above accordingly.
Thank you very much @scaramallion and @jstutters.
Most helpful comment
I've used the following to convert a dataset to a dict (for storing as JSON) if it's any help. The
reprcall to populate the elements feels like hack though.