Diff of /cmac/aux_dicom.py [000000] .. [4cda31]

Switch to unified view

a b/cmac/aux_dicom.py
1
import os
2
import glob
3
import pydicom
4
import numpy as np
5
import nibabel as nib
6
from dipy.align.reslice import reslice
7
from dipy.align.imaffine import AffineMap
8
9
def extract_cosines(ImageOrientationPatient):
10
    row_cosine    = np.array(ImageOrientationPatient[:3])
11
    column_cosine = np.array(ImageOrientationPatient[3:])
12
    slice_cosine  = np.cross(row_cosine, column_cosine)
13
    return row_cosine, column_cosine, slice_cosine
14
15
def read_RefDs(dicom_folder_path):
16
    cine_dicom_files = glob.glob(dicom_folder_path)
17
    SliceLocations   = [pydicom.read_file(cine_dicom_file).SliceLocation 
18
                        for cine_dicom_file in cine_dicom_files]
19
    SliceOriginID    = np.array(SliceLocations, dtype=float).argmin()
20
    
21
    RefDs = pydicom.read_file(cine_dicom_files[SliceOriginID])
22
    ImageOrientationPatient = RefDs.ImageOrientationPatient
23
    ImagePositionPatient    = np.array(list(RefDs.ImagePositionPatient), dtype=float)
24
    Zooms                   = np.array(list(RefDs.PixelSpacing) + [RefDs.SliceThickness], dtype=float)
25
    
26
    return ImageOrientationPatient, ImagePositionPatient, Zooms
27
28
def read_affine_info(dicom_folder_path, viewer='slicer'):
29
    
30
    ImageOrientationPatient, ImagePositionPatient, Zooms = read_RefDs(dicom_folder_path)
31
    
32
    affine_axial        = np.diag(list(Zooms)+[1])
33
    affine_axial[:3,3] += ImagePositionPatient
34
    
35
    row_cos, column_cos, slice_cos = extract_cosines(ImageOrientationPatient)
36
    
37
    ijk2ras = np.stack((row_cos, column_cos, slice_cos))
38
    if viewer == "slicer":
39
        ijk2ras = (ijk2ras*np.array([-1,-1,1])).T
40
        ImagePositionPatient = ImagePositionPatient*np.array([-1,-1,1])
41
42
    affine  = np.stack((ijk2ras[:,0]*Zooms[0],
43
                        ijk2ras[:,1]*Zooms[1],
44
                        ijk2ras[:,2]*Zooms[2],
45
                        ImagePositionPatient), axis=1)
46
    
47
    return ijk2ras, np.vstack((affine,[[0,0,0,1]])), affine_axial   
48
49
def reslice_3d(domain_nifti, codomain_nifti, mode='linear'):
50
    
51
    affine_map = AffineMap(affine=np.eye(4),
52
                  domain_grid_shape=domain_nifti.shape, domain_grid2world=domain_nifti.affine, 
53
                  codomain_grid_shape=codomain_nifti.shape, codomain_grid2world=codomain_nifti.affine)
54
55
    return nib.Nifti1Image(affine_map.transform(codomain_nifti.get_fdata(),mode),domain_nifti.affine)
56
57
def reslice_4d(domain_nifti, codomain_nifti, mode='linear'):
58
    
59
    reslice_arr = np.zeros(domain_nifti.shape[:3]+(codomain_nifti.shape[-1],))
60
    affine_map  = AffineMap(affine=np.eye(4),
61
                  domain_grid_shape=domain_nifti.shape[:3],     domain_grid2world=domain_nifti.affine, 
62
                  codomain_grid_shape=codomain_nifti.shape[:3], codomain_grid2world=codomain_nifti.affine)
63
    
64
    for frame_id in range(reslice_arr.shape[-1]):
65
        reslice_arr[:,:,:,frame_id] += affine_map.transform(codomain_nifti.get_fdata()[:,:,:,frame_id],mode)
66
    
67
    return nib.Nifti1Image(reslice_arr, domain_nifti.affine)
68
69
70
def resample_nifti(subject_nifti, resolution=(1.5, 1.5), Nz=16, order=1, mode='nearest'):
71
    """Resample a 3D or 4D (3D+time) cine-MRI nifti to a new in-plane `resolution` with `Nz` slices."""
72
 
73
    data   = subject_nifti.get_fdata()
74
    affine = subject_nifti.affine
75
    zooms  = subject_nifti.header.get_zooms()[:3]
76
    
77
    new_zooms = (resolution[0], resolution[1], (zooms[2] * data.shape[2]) / Nz)
78
     
79
    data_resampled, affine_resampled = reslice(data, affine, zooms, new_zooms, order=order, mode=mode)
80
    subject_nifti_resampled = nib.Nifti1Image(data_resampled, affine_resampled)
81
     
82
    x=subject_nifti_resampled.header.get_zooms()[:3]
83
    y=new_zooms
84
    if not np.allclose(x,y, rtol=1e-02):
85
        print(subject_nifti.affine,affine)
86
        print(zooms)
87
        print(x,y)
88
        warnings.warn('Output resolutions are different than expected!')
89
         
90
    return subject_nifti_resampled