0

A very simple pydicom examples involves reading a file and then outputting the Series Time:

import pydicom
info = pydicom.dcmread("file.dcm")
print(info.SeriesTime)

So for an object having been read, dot notation is a working alternative to more complicated constructs such as print(info[pydicom.tag.Tag((0x0008, 0x0031))]) or print(info[0x0008, 0x0031]). Nice.

Now, pydicom supports reading only some tags for improved performance:

info = pydicom.dcmread("file.dcm", specific_tags=['SeriesTime', ])

I dislike the use of string constants in code. So what are readable alternatives to 'SeriesTime' in the above example? specific_tags=[pydicom.tag.Tag((0x0008, 0x0031)), ] is not particularly readable.

Ideally, I would expect to be able to access a dictionary of tags by dot notation, such as pydicom.allTags.SeriesTime, but I cannot seem to find that.

2 Answers 2

2

Here's another relatively brief way to get dotted access to the pydicom dictionary:

from pydicom.datadict import tag_for_keyword
from pydicom.tag import Tag

class DottedDcmDict(object):
    def __getattr__(self, name):
        tag = tag_for_keyword(name)
        if tag:
            return Tag(tag)
        raise AttributeError("Not a valid DICOM identifier")

dd = DottedDcmDict()
print(dd.SeriesTime)
(0008, 0031)

1

What you are looking for is the data dictionary. In Pydicom you can find it here: pydicom.datadict.DicomDictionary but this is a dict of tuples which is not really suited to access by dot notation. For example, to retrieve 'SeriesTime' you would have to write pydicom.datadict.DicomDictionary[524337][4] which is neither readable or guaranteed to remain valid over updates of Pydicom(although I doubt it would change often if at all).

You could implement this yourself though with a namedtuple:

from collections import namedtuple
import pydicom

def get_dict_as_namedtuple(pdict):
    # some keywords are empty, check for those
    keywords_list = [pdict[i][4] for i in pdict if pdict[i][4].strip() != '']
    Keywords = namedtuple('Keywords', keywords_list)
    # unpack the list as positional arguments
    return Keywords(*keywords_list)

dicom_tags = get_dict_as_namedtuple(pydicom.datadict.DicomDictionary)

print(dicom_tags.SeriesTime)
# prints 'SeriesTime'

Or my initial, less elegant solution (tab autocompletion does not work for me with this solution):
(example code for AttributeDict from the Fabric codebase found via this answer)

import pydicom
class AttributeDict(dict):

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            # to conform with __getattr__ spec
            raise AttributeError(key)

    def __setattr__(self, key, value):
        self[key] = value

    def first(self, *names):
        for name in names:
            value = self.get(name)
            if value:
                return value

def get_data_dict(pydicom_data_dict):
        data_dict = AttributeDict({})
        for entry in pydicom_data_dict:
            keyword = pydicom_data_dict[entry][4]
            data_dict[keyword] = keyword
        return data_dict

pydicom_data_dict = get_data_dict(pydicom.datadict.DicomDictionary)
print(pydicom_data_dict.SeriesTime)
#prints 'SeriesTime'

Not the answer you're looking for? Browse other questions tagged or ask your own question.