DICOM Images read with GDCMSeriesFileNames or list of paths

I am using SimpleITK to analyse Dynamic PET Data. I have a folder with 148 * N images (with N the number of frames of my Dynamic PET) and I want to separate the images of each frames. Firstly, I created one subfolder for each frame with the corresponding images.

>folder #Folder of dynamic data
   >subfolder1 #Subfolder with images of Frame 1
      >image1, image2, ..., image148
   >subfolder2 #Subfolder with images of Frame 2
      >image149 image 150, ..., image296

I was reading my images as following:

series_reader = sitk.ImageSeriesReader()
image = sitk.ReadImage(series_reader.GDCMSeriesFileNames(path_subfolder1))

Creating all these subfolders is not very user-friendly so I try to store all the paths of the images in lists :

frame1 = [image1, ..., image148]
frame2 = [image149, ..., image296]
...
frame_list = [frame1, frame2, ..., frameN]

And reading images like this:

image = sitk.ReadImage(frame_list[0])

The problem is that when I am looking at the value of a voxel located in the same coordinates (x, y, z), I don't get the same value with the 2 methods. It seems that with series_reader.GDCMSeriesFileNames() SimpleITK retrieve some information about the DICOM image like the Origin.

Which information are retrieved by SimpleITK to create his images with series_reader.GDCMSeriesFileNames() that I need to have the exactly same image? Or is there another way to have the same image using list of paths?

P.S. : In this post, all the variables named with 'image' are the paths to the images not a SimpleITK Image object.

Edit : In my case, all of my frames have got the same series number so I can't use series_reader.GDCMSeriesFileNames(path_folder, series_ID)

Upvotes: 3

Views: 5115

Answers (4)

Andras Lasso
Andras Lasso

Reputation: 1

GDCM can deal with simple cases, such as a single 3D volume in a series, but not prepared to handle time series. If you need to load dynamic data sets then you need to use something more sophisticated.

3D Slicer's DICOM importer indexes an entire folder structure and determines what can be loaded from them, including 2D/3D/4D data sets with non-axis aligned, tilted-gantry, variable-slice-spacing acquisitions; images, segmentations, transformations, structured reports, RT plan/image/structure set/dose, and many other information object types. You can then save the result as nrrd and process it further using SimpleITK.

DCM2NIIX tool can also convert some dynamic images to nrrd or nifti.

Upvotes: 0

The temporary solution I find is the following one :

1) Creating lists containing every slice as Image Object using sitk.ImageFileReader():

frame1 = [Image1, ..., Image148]
frame2 = [Image149, ..., Image296]
...
frame_list = [frame1, frame2, ..., frameN]

NB : Here we deal with sitk Image Object and not images path as in my first post

2) Modifying every images seriesID in the DICOM header:

count = 1
for frames in frame_list:
  for images in frames:
    newID = images.GetMetaData('0020|000e') + str(count)
    images.SetMetaData('0020|000e', newID)
  count += 1

3) Writing the images with their new seriesID in a buffer folder using writer = sitk.ImageFileWriter() and writer.KeepOriginalImageUIDOn()

4) Storing in a dictionnary all the different series ID with the associated images path using @blowekamp method :

series_dic = { series_id: reader.GetGDCMSeriesFileNames(path, series_id) for series_id in reader.GetGDCMSeriesIDs(path) }

5) Reading the series and store them in a list:

for keys in series_dic:
  Img_list.append(sitk.ReadImage(series_dic[keys]))

6) Finally I remove the buffer folder with shutil.rmtree(path, ignore_errors=True)

This is not very optimized because I must write new images then delete it. If you have a better answer feel free to comment!

Upvotes: 0

blowekamp
blowekamp

Reputation: 1431

There is no need to split the series into separate directories. You can get the list of seriesIDs in a directory with the itk::simple::ImageSeriesReader::GetGDCMSeriesIDs method.

You can easily create a map for seriesID to file lists with the following one liner: series_dic = { series_id: reader.GetGDCMSeriesFileNames(path, series_id) for series_id in reader.GetGDCMSeriesIDs(path) }

By using the GetGDCMSeriesFileNames method you should get all the files is the proper order sorted by their physical locations, with your manual method you are not.

If this automatic approach does not work for your particular scanner or acquisition process, you will have to manually load the DICOMS dictionaries, separate them by series_id, and then properly sort them based on the proper DICOM tags for your acquisition.

Upvotes: 2

Rishabh Agrahari
Rishabh Agrahari

Reputation: 3717

As far as I've understood your question, you have got a folder with all Dicom slices and you want to read them as a single volume so that you could access voxel values at any given coordinate. Try reading your Dicom images by this code snippet:

reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(path_subfolder1)
reader.SetFileNames(dicom_names)
image = reader.Execute()

Now, image is your 3D volume containing all slices present in path_subfolder1 and you can access voxel values, spacing, directions, origin etc.

I hope this helps, if not feel free to comment down below.

Upvotes: 0

Related Questions