2

I'm reading in a DICOM with pydicom.read_file() like this:

x = pydicom.read_file(/path/to/dicom/)

This returns an instance of FileDataset but I get an error when trying to access a value like this:

x[0x20,0x32]
OUTPUT: *** KeyError: (0020, 0032)

I also tried accessing the value like this:

x.ImagePositionPatient
OUTPUT: *** AttributeError: 'FileDataset' object has no attribute 'ImagePositionPatient'

The reason this confuses me is because when I look at all the values using x.values I see the field is in fact present:

(0020, 0032) Image Position (Patient)

How can the key be missing if I can clearly see that it exists?

I'm not an expert on PyDICOM but it should work just like a regular Python dictionary.

nikebol906
  • 152
  • 1
  • 7
  • Can you provide a link to the package? – not2qubit Dec 12 '22 at 20:20
  • 1
    @not2qubit Here is a link to the FileDataset doc which is what I'm currently trying to access: https://pydicom.github.io/pydicom/stable/reference/generated/pydicom.dataset.FileDataset.html – nikebol906 Dec 12 '22 at 20:32
  • It is not a python dictionary, but yet, you're right, you should be able to access it like that. I've never encountered such problem (not an expert neither. But I've played more than once with pydicom, and this is exactly how I get attributes I want, and how I check manually their existence). Do you have a `.dcm` (small) example you can share? – chrslg Dec 12 '22 at 20:39
  • I don't know how I would upload a DICOM nor am I sure that I should since they can sometime contain sensitive information. Is there something in the `.dcm` file you would like me to share? – nikebol906 Dec 12 '22 at 20:48
  • Maybe the tag is inside a sequence? That would be the case if you have an enhanced SOP class (Enhanced MR, Enhanced CT etc), where it would be inside a per-frame functional group sequence. – MrBean Bremen Dec 12 '22 at 20:52
  • If it is medical dicom, you probably shouldn't upload them, indeed (I work with dicom of bolts and screws, so I don't have the same problems with my "patients"). Maybe `for k in x: print(k)` result? – chrslg Dec 12 '22 at 20:57
  • @MrBeanBremen Any suggestions on how to check if I have an enhanced SOP class or not? – nikebol906 Dec 12 '22 at 21:00
  • Just check the SOP Class UID (0008, 0016). You also may print out all tags, including inside sequences, using something like what I showed [in this answer](https://stackoverflow.com/a/68320719/12480730). – MrBean Bremen Dec 12 '22 at 21:02
  • @chrslg I ran that for loop and it printed out A LOT of things but I don't actually see the filed I am trying to access. What is the difference between doing `x.values` and `for k in x: print(k)` – nikebol906 Dec 12 '22 at 21:04
  • @MrBeanBremen You are correct. This is indeed an Enhanced MR Image Storage class. Thanks for helping me figure that out but what should I do to access the value I need? – nikebol906 Dec 12 '22 at 21:05
  • well, mine shows only what you can get by directly indexing `x[..,...]`. So that's consistent: you don't see 20,32 in the list, because, indeed, there is no `x[0x20,0x32]`. So, now, back in x.values, there should be some "organization" to the output. And (20,32) should not be with with the rest of the attributes. It should be either under a section, or indented as subindex of another index. – chrslg Dec 12 '22 at 21:07
  • I'll write an answer - this gets a bit much for comments... – MrBean Bremen Dec 12 '22 at 21:09
  • For example on one of my dcm, I have a `(0014, 2206) Coordinate System Axis Description` in `x.values` output. But yet I can't `x[0x14,0x2206]`. Because that is a subindex of `(0014, 2204) Coordinate System Axes Sequence`. Which shows in `x.values` output. So to access it, I need to `x[0x14,0x2204][0][0x14, 0x2206]` (or `[1]`, `[2]`, `[3]`, `[4]` instead of `[0]`, since it is a sequence of 5 axes) – chrslg Dec 12 '22 at 21:10
  • So, said otherwise: is there not any context to your (0x20, 0x32) in the lines before, that would indicate how to access it? – chrslg Dec 12 '22 at 21:11
  • 1
    May be helpful: Sequences in DICOM - https://stackoverflow.com/a/46690734/5779732 – Amit Joshi Dec 13 '22 at 06:33

1 Answers1

3

For Enhanced SOP classes (Enhanced CT, Enhanced MR and some more) many tags are located in sequences: in the Shared Functional Groups Sequence for tags that are common for all slices, and in the Per frame Functional Groups Sequence for tags specific to each slice, with an item for each slice.
(note that the links are specific to Enhanced MR to match your dataset)

Image Position (Patient) is a slice-specific tag, so you can access the value for a each slice in the corresponding item. The functional group sequences do not directly contain the tags, but they are nested in another sequence - in the case of Image Position (Patient) this is the Plane Position Sequence. To access these values in pydicom you can do something like:

ds = dcmread(filename)
positions = []
for item in ds.PerFrameFunctionalGroupsSequence:
    positions.append(item.PlanePositionSequence[0].ImagePositionPatient)
print(positions)

This will give you the image position for each slice. You should check that you have the correct SOP class, of course, and add checks for existence of the tags. Depending on your use case, you may only need the first of these positions, in which case you wouldn't have to iterate over the items.

MrBean Bremen
  • 14,916
  • 3
  • 26
  • 46
  • Thank you. I had to go a few layers deeper to get what I actually needed but at least I understand now why I couldn't access the values I needed. Thanks again! – nikebol906 Dec 12 '22 at 21:29