Skip to content

Commit 5625c70

Browse files
committed
account for slice dir inversion
small fixes please the linter the linter is stupid
1 parent 6f53b91 commit 5625c70

File tree

2 files changed

+40
-28
lines changed

2 files changed

+40
-28
lines changed

src/mrinufft/io/siemens.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from __future__ import annotations
44

55
import numpy as np
6-
from .utils import siemens_quat_to_rot_mat
6+
from .utils import siemens_quat_to_rot_mat, nifti_affine
77

88

99
def read_siemens_rawdat(
@@ -76,6 +76,7 @@ def read_siemens_rawdat(
7676
"n_slices": int(twixObj.image.NSli),
7777
"n_average": int(twixObj.image.NAve),
7878
"orientation": siemens_quat_to_rot_mat(twixObj.image.slicePos[0][-4:]),
79+
"affine": nifti_affine(twixObj),
7980
"acs": None,
8081
}
8182
if "refscan" in twixObj.keys():

src/mrinufft/io/utils.py

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,16 @@ def add_phase_to_kspace_with_shifts(kspace_data, kspace_loc, normalized_shifts):
3838
return kspace_data * phase
3939

4040

41-
def siemens_quat_to_rot_mat(quat):
41+
def siemens_quat_to_rot_mat(quat, return_det=False):
4242
"""
4343
Calculate the rotation matrix from Siemens Twix quaternion.
4444
4545
Parameters
4646
----------
4747
quat : np.ndarray
4848
The quaternion from the Siemens Twix file.
49+
return_det : bool
50+
Whether to return the determinent of the rotation before norm
4951
5052
Returns
5153
-------
@@ -56,11 +58,15 @@ def siemens_quat_to_rot_mat(quat):
5658
R = np.zeros((4, 4))
5759
R[:3, :3] = Rotation.from_quat([quat[1], quat[2], quat[3], quat[0]]).as_matrix()
5860
R[:, (0, 1)] = R[:, (1, 0)]
59-
if np.linalg.det(R[:3, :3]) < 0:
61+
det = np.linalg.det(R[:3, :3])
62+
if det < 0:
6063
R[2] = -R[2]
6164
R[-1, -1] = 1
65+
if return_det:
66+
return R, det
6267
return R
6368

69+
6470
def nifti_affine(twixObj):
6571
"""
6672
Calculate the affine transformation matrix from Siemens Twix object.
@@ -78,51 +84,56 @@ def nifti_affine(twixObj):
7884
"""
7985
# required keys
8086
keys = {
81-
'dthick': ('sSliceArray', 'asSlice', '0', 'dThickness'),
82-
'dread' : ('sSliceArray', 'asSlice', '0', 'dReadoutFOV'),
83-
'dphase': ('sSliceArray', 'asSlice', '0', 'dPhaseFOV'),
84-
'lbase' : ('sKSpace', 'lBaseResolution'),
85-
'lphase': ('sKSpace', 'lPhaseEncodingLines'),
86-
'ucdim' : ('sKSpace', 'ucDimension'),
87-
}
88-
sos = ('sKSpace', 'dSliceOversamplingForDialog')
89-
rot = siemens_quat_to_rot_mat(twixObj.image.slicePos[0][-4:])
87+
"dthick": ("sSliceArray", "asSlice", "0", "dThickness"),
88+
"dread": ("sSliceArray", "asSlice", "0", "dReadoutFOV"),
89+
"dphase": ("sSliceArray", "asSlice", "0", "dPhaseFOV"),
90+
"lbase": ("sKSpace", "lBaseResolution"),
91+
"lphase": ("sKSpace", "lPhaseEncodingLines"),
92+
"ucdim": ("sKSpace", "ucDimension"),
93+
}
94+
sos = ("sKSpace", "dSliceOversamplingForDialog")
95+
rot, det = siemens_quat_to_rot_mat(twixObj.image.slicePos[0][-4:], True)
9096
my = twixObj.hdr.MeasYaps
9197

9298
for k in keys.keys():
9399
if keys[k] not in my:
94100
return rot
95101

96-
dthick = my[keys['dthick']]
97-
fov = np.array([
98-
my[keys['dread']],
99-
my[keys['dphase']],
102+
dthick = my[keys["dthick"]]
103+
fov = np.array(
104+
[
105+
my[keys["dread"]],
106+
my[keys["dphase"]],
100107
dthick * (1 + my[sos] if sos in my else 1),
101-
])
102-
103-
lpart = ('sKSpace', 'lPartitions')
104-
res = np.array([
105-
my[keys['lbase']],
106-
my[keys['lphase']],
107-
my[lpart] if my[keys['ucdim']] == 4 and lpart in my else 1,
108-
])
108+
]
109+
)
110+
111+
lpart = ("sKSpace", "lPartitions")
112+
res = np.array(
113+
[
114+
my[keys["lbase"]],
115+
my[keys["lphase"]],
116+
my[lpart] if my[keys["ucdim"]] == 4 and lpart in my else 1,
117+
]
118+
)
109119

110120
scale = np.diag([*(fov / res), 1])
111121

112122
offset = twixObj.image.slicePos[0][:3]
113123

114-
center = [-fov[0]/2,
115-
-fov[1]/2,
116-
-(fov[2] - (my[sos] * dthick if sos in my else 0))/2,
117-
1]
124+
fovz = fov[2] - (my[sos] * dthick if sos in my else 0)
125+
center = [-fov[0] / 2, -fov[1] / 2, -fovz / 2, 1]
118126

119127
t = (rot @ center)[:3] - offset
128+
if det < 0:
129+
t[2] = (rot @ center)[2] * 2 - t[2]
120130

121131
full_mat = rot @ scale
122132
full_mat[:3, 3] = t
123133

124134
return full_mat
125135

136+
126137
def remove_extra_kspace_samples(kspace_data, num_samples_per_shot):
127138
"""Remove extra samples from k-space data.
128139

0 commit comments

Comments
 (0)