2

I am having trouble with dcmread() on a DICOM file that does exists at given path. I'm not sure what went wrong. Here is my code:

import pydicom

f = "/exact/path/hi.dcm"
fn = get_testdata_file(f)
ds = pydicom.dcmread(fn)

ds.SOPClassUID = ds.MediaStorageSOPClassUID

I am getting below error:

Traceback (most recent call last):
  File "addfields.py", line 14, in <module>
    ds = pydicom.dcmread(fn)
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/pydicom/filereader.py", line 871, in dcmread
    force=force, specific_tags=specific_tags)
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/pydicom/filereader.py", line 668, in read_partial
    preamble = read_preamble(fileobj, force)
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/pydicom/filereader.py", line 605, in read_preamble
    preamble = fp.read(128)
AttributeError: 'NoneType' object has no attribute 'read'

But I am not sure why, because "hi.dcm" is a file that exists (path is correct) and has metadata inside. I do not know what is preamble and whether it present in the image I am dealing with.

Amit Joshi
  • 15,448
  • 21
  • 77
  • 141
j. doe
  • 163
  • 3
  • 11
  • Some toolkits do not process instances without preamble; not sure if pydicom is one of them. Preamble may not present even though metadata present. Many viewers and dump utilities also load the dataset without without preamble properly; that does not mean all is well. Further read about this [here](https://stackoverflow.com/a/58340554/5779732). – Amit Joshi Aug 18 '20 at 08:27
  • About your problem: 1) Make sure if pydicom can read instances without preamble. 2) If yes, try to figure out how to configure it to do it. May be some initial configuration or some parameter to some method or setting some property. 3) If no, you have to insert preamble yourself; refer to link in above comment. – Amit Joshi Aug 18 '20 at 08:29
  • 1
    @AmitJoshi - I added a a couple of notes to the answer to clarify the confusion. The error handling shall probably be changed in pydicom . – MrBean Bremen Aug 18 '20 at 09:52

1 Answers1

9

Disclaimer: I am a contributor to pydicom.

The error happens because get_testdata_file returns None, which is then used as the filename. The error message itself is a bit misleading - it would probably be better to raise FileNotFound or ValueError in this case (Update: it raises TypeError in current pydicom). What happens instead is that the first thing that is read is the preamble (a marker for DICOM images that consists of 128 zero bytes followed by 'DICM'), and while trying to read this it crashes because of a file pointer which is None.

Here is the documentation for get_testdata_file:

Return an absolute path to the first matching dataset with filename name.

First searches the local pydicom data store, then any locally available external sources, and finally the files available in the pydicom/pydicom-data repository.

So this is a convenience function mainly to find pydicom test data files.
If you already have the file path, you can just use it:

import pydicom

fn = "/exact/path/hi.dcm"
ds = pydicom.dcmread(fn)

As for the preamble, if the DICOM file has no preamble (old ACR-NEMA format), you can read such files using the force=True argument:

ds = pydicom.dcmread(fn, force=True)

Though I would only use this if you really have such files, because it also tries to handle non-DICOM files as DICOM, which may result in some unexpected exceptions. As already mentioned, the error in this case is not related to a missing preamble, but to an incorrect file path.

UPDATE:
Since version 2.1 of pydicom this behavior has changed. dcmread will now raise TypeError with a meaningful message if passed None.

MrBean Bremen
  • 14,916
  • 3
  • 26
  • 46