Skip to content
This repository was archived by the owner on Dec 27, 2022. It is now read-only.

Commit f15f054

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents 9526e2a + fa77ed6 commit f15f054

File tree

2 files changed

+78
-54
lines changed

2 files changed

+78
-54
lines changed

preafq/qc.py

Lines changed: 62 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,35 @@
1-
import nibabel as nib
21
import matplotlib
3-
matplotlib.use('agg')
2+
import nibabel as nib
3+
44
import matplotlib.pyplot as plt
55
import numpy as np
6-
from nipype.utils.filemanip import fname_presuffix
76
import os.path as op
87
from dipy.segment.mask import median_otsu
98
from io import BytesIO
109
from nipype.utils.filemanip import save_json
1110
import base64
1211

12+
matplotlib.use('agg')
13+
14+
1315
def reorient_array(data, aff):
1416
# rearrange the matrix to RAS orientation
1517
orientation = nib.orientations.io_orientation(aff)
1618
data_RAS = nib.orientations.apply_orientation(data, orientation)
1719
# In RAS
18-
return nib.orientations.apply_orientation(data_RAS,
19-
nib.orientations.axcodes2ornt("IPL"))
20+
return nib.orientations.apply_orientation(
21+
data_RAS,
22+
nib.orientations.axcodes2ornt("IPL")
23+
)
24+
2025

2126
def mplfig(data, outfile=None, as_bytes=False):
2227
fig = plt.figure(frameon=False, dpi=data.shape[0])
2328
fig.set_size_inches(float(data.shape[1])/data.shape[0], 1)
2429
ax = plt.Axes(fig, [0., 0., 1., 1.])
2530
ax.set_axis_off()
2631
fig.add_axes(ax)
27-
ax.imshow(data, aspect=1, cmap=plt.cm.Greys_r) # used to be aspect="normal"
32+
ax.imshow(data, aspect=1, cmap=plt.cm.Greys_r) # previous aspect="normal"
2833
if outfile:
2934
fig.savefig(outfile, dpi=data.shape[0], transparent=True)
3035
plt.close()
@@ -43,7 +48,7 @@ def mplfigcontour(data, outfile=None, as_bytes=False):
4348
ax = plt.Axes(fig, [0., 0., 1., 1.])
4449
ax.set_axis_off()
4550
fig.add_axes(ax)
46-
51+
4752
bg = np.zeros(data.shape)
4853
bg[:] = np.nan
4954
ax.imshow(bg, aspect=1, cmap=plt.cm.Greys_r) # used to be aspect="normal"
@@ -59,23 +64,41 @@ def mplfigcontour(data, outfile=None, as_bytes=False):
5964
base64_jpgData = base64.b64encode(IObytes.read())
6065
return base64_jpgData.decode("ascii")
6166

67+
6268
def load_and_reorient(filename):
6369
img = nib.load(filename)
6470
data, aff = img.get_data(), img.affine
6571
data = reorient_array(data, aff)
6672
return data
6773

74+
6875
def reshape3D(data, n=256):
69-
return np.pad(data, (((n-data.shape[0])//2, ((n-data.shape[0]) + (data.shape[0]%2 >0))//2),
70-
((n-data.shape[1])//2, ((n-data.shape[1]) + (data.shape[1]%2 >0))//2),
71-
(0,0)),
72-
"constant", constant_values = (0,0))
76+
return np.pad(data, (
77+
(
78+
(n-data.shape[0]) // 2,
79+
((n-data.shape[0]) + (data.shape[0] % 2 > 0)) // 2
80+
),
81+
(
82+
(n-data.shape[1]) // 2,
83+
((n-data.shape[1]) + (data.shape[1] % 2 > 0)) // 2
84+
),
85+
(0, 0)
86+
), "constant", constant_values=(0, 0))
87+
7388

7489
def reshape4D(data, n=256):
75-
return np.pad(data, (((n-data.shape[0])//2, ((n-data.shape[0]) + (data.shape[0]%2 >0))//2),
76-
((n-data.shape[1])//2, ((n-data.shape[1]) + (data.shape[1]%2 >0))//2),
77-
(0,0), (0,0)),
78-
"constant", constant_values = (0,0))
90+
return np.pad(data, (
91+
(
92+
(n-data.shape[0]) // 2,
93+
((n-data.shape[0]) + (data.shape[0] % 2 > 0)) // 2
94+
),
95+
(
96+
(n-data.shape[1]) // 2,
97+
((n-data.shape[1]) + (data.shape[1] % 2 > 0)) // 2
98+
),
99+
(0, 0), (0, 0)
100+
), "constant", constant_values=(0, 0))
101+
79102

80103
def get_middle_slices(data, slice_direction):
81104
slicer = {"ax": 0, "cor": 1, "sag": 2}
@@ -84,13 +107,14 @@ def get_middle_slices(data, slice_direction):
84107
slice_num = int(num_slices / 2)
85108
all_data_slicer[slicer[slice_direction]] = slice_num
86109
tile = data[tuple(all_data_slicer)]
87-
110+
88111
# make it a square
89112
N = max(tile.shape[:2])
90113
tile = reshape3D(tile, N)
91-
114+
92115
return tile
93116

117+
94118
def nearest_square(limit):
95119
answer = 0
96120
while (answer+1)**2 < limit:
@@ -100,7 +124,8 @@ def nearest_square(limit):
100124
else:
101125
return answer + 1
102126

103-
def create_sprite_from_tiles(tile, out_file = None, as_bytes=False):
127+
128+
def create_sprite_from_tiles(tile, out_file=None, as_bytes=False):
104129
num_slices = tile.shape[-1]
105130
N = nearest_square(num_slices)
106131
M = int(np.ceil(num_slices/N))
@@ -109,24 +134,24 @@ def create_sprite_from_tiles(tile, out_file = None, as_bytes=False):
109134

110135
if len(tile.shape) == 3:
111136
mosaic = np.zeros((N*tile.shape[0], M*tile.shape[0]))
112-
else:
137+
else:
113138
mosaic = np.zeros((N*tile.shape[0], M*tile.shape[0], tile.shape[-2]))
114-
139+
115140
mosaic[:] = np.nan
116141
helper = np.arange(N*M).reshape((N, M))
117-
142+
118143
for t in range(num_slices):
119144
x, y = np.nonzero(helper == t)
120145
xmin = x[0] * pix
121146
xmax = (x[0] + 1) * pix
122147
ymin = y[0] * pix
123148
ymax = (y[0] + 1) * pix
124-
149+
125150
if len(tile.shape) == 3:
126-
mosaic[xmin:xmax, ymin:ymax] = tile[:,:,t]
151+
mosaic[xmin:xmax, ymin:ymax] = tile[:, :, t]
127152
else:
128-
mosaic[xmin:xmax, ymin:ymax, :] = tile[:,:,:,t]
129-
153+
mosaic[xmin:xmax, ymin:ymax, :] = tile[:, :, :, t]
154+
130155
if as_bytes:
131156
img = mplfig(mosaic, out_file, as_bytes=as_bytes)
132157
return dict(img=img, N=N, M=M, pix=pix, num_slices=num_slices)
@@ -138,31 +163,31 @@ def create_sprite_from_tiles(tile, out_file = None, as_bytes=False):
138163

139164

140165
def createSprite4D(dwi_file):
141-
166+
142167
# initialize output dict
143168
output = []
144169

145170
# load the file
146-
dwi = load_and_reorient(dwi_file)[:,:,:,1:]
171+
dwi = load_and_reorient(dwi_file)[:, :, :, 1:]
147172

148173
# create tiles from center slice on each orientation
149174
for orient in ['sag', 'ax', 'cor']:
150175
tile = get_middle_slices(dwi, orient)
151176

152-
# create sprite images for each
177+
# create sprite images for each
153178
results = create_sprite_from_tiles(tile, as_bytes=True)
154179
results['img_type'] = '4dsprite'
155180
results['orientation'] = orient
156181
output.append(results)
157182

158183
return output
159184

185+
160186
def createB0_ColorFA_Mask_Sprites(b0_file, colorFA_file, mask_file):
161187
colorfa = load_and_reorient(colorFA_file)
162-
b0 = load_and_reorient(b0_file)[:,:,:,0]
188+
b0 = load_and_reorient(b0_file)[:, :, :, 0]
163189
anat_mask = load_and_reorient(mask_file)
164190

165-
166191
N = max(*b0.shape[:2])
167192

168193
# make a b0 sprite
@@ -173,7 +198,7 @@ def createB0_ColorFA_Mask_Sprites(b0_file, colorFA_file, mask_file):
173198

174199
# make a colorFA sprite, masked by b0
175200
Q = reshape4D(colorfa, N)
176-
Q[mask == False] = np.nan
201+
Q[np.logical_not(mask)] = np.nan
177202
Q = np.moveaxis(Q, -2, -1)
178203
outcolorFA = create_sprite_from_tiles(Q, as_bytes=True)
179204
outcolorFA['img_type'] = 'brainsprite'
@@ -186,23 +211,23 @@ def createB0_ColorFA_Mask_Sprites(b0_file, colorFA_file, mask_file):
186211
return outb0, outcolorFA, outmask
187212

188213

189-
def create_report_json(dwi_corrected_file, eddy_rms, eddy_report,
190-
color_fa_file, anat_mask_file,
214+
def create_report_json(dwi_corrected_file, eddy_rms, eddy_report,
215+
color_fa_file, anat_mask_file,
191216
outpath=op.abspath('./report.json')):
192217

193218
report = {}
194219
report['dwi_corrected'] = createSprite4D(dwi_corrected_file)
195220

196-
b0, colorFA, mask = createB0_ColorFA_Mask_Sprites(dwi_corrected_file,
197-
color_fa_file,
198-
anat_mask_file)
221+
b0, colorFA, mask = createB0_ColorFA_Mask_Sprites(dwi_corrected_file,
222+
color_fa_file,
223+
anat_mask_file)
199224
report['b0'] = b0
200225
report['colorFA'] = colorFA
201226
report['anat_mask'] = mask
202227

203228
with open(eddy_report, 'r') as f:
204229
report['eddy_report'] = f.readlines()
205-
230+
206231
report['eddy_params'] = np.genfromtxt(eddy_rms).tolist()
207232

208233
save_json(outpath, report)

preafq/run_1.py

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import os.path as op
2-
from glob import glob
32
from shutil import copyfile
43

54
import nipype.interfaces.freesurfer as fs
65
import nipype.interfaces.fsl as fsl
76
import nipype.interfaces.io as nio
87
import nipype.interfaces.utility as niu
98
import nipype.pipeline.engine as pe
10-
from nipype.algorithms.rapidart import ArtifactDetect
119
from nipype.interfaces.dipy import DTI
1210
from nipype.workflows.dmri.fsl.artifacts import all_fsl_pipeline
1311

@@ -39,7 +37,7 @@ def run_preAFQ(dwi_file, dwi_file_AP, dwi_file_PA, bvec_file, bval_file,
3937
prep.inputs.inputnode.in_bval = bval_file
4038
eddy = prep.get_node('fsl_eddy')
4139
eddy.inputs.repol = True
42-
eddy.inputs.niter = 1 # TODO: change back to 5 when running for real
40+
eddy.inputs.niter = 1 # TODO: change back to 5 when running for real
4341

4442
merge = pe.Node(fsl.Merge(dimension='t'), name="mergeAPPA")
4543
merge.inputs.in_files = [dwi_file_AP, dwi_file_PA]
@@ -154,11 +152,11 @@ def get_orig(subjects_dir, sub):
154152
wf.connect(prep, "fsl_eddy.out_movement_rms",
155153
datasink, "preafq.qc.@eddyparamsrms")
156154
wf.connect(prep, "fsl_eddy.out_outlier_report",
157-
datasink, "preafq.qc.@eddyparamsreport")
155+
datasink, "preafq.qc.@eddyparamsreport")
158156
wf.connect(prep, "fsl_eddy.out_restricted_movement_rms",
159-
datasink, "preafq.qc.@eddyparamsrestrictrms")
157+
datasink, "preafq.qc.@eddyparamsrestrictrms")
160158
wf.connect(prep, "fsl_eddy.out_shell_alignment_parameters",
161-
datasink, "preafq.qc.@eddyparamsshellalign")
159+
datasink, "preafq.qc.@eddyparamsshellalign")
162160

163161
wf.connect(get_tensor, "out_file", datasink, "preafq.dti.@tensor")
164162
wf.connect(get_tensor, "fa_file", datasink, "preafq.dti.@fa")
@@ -181,21 +179,22 @@ def get_orig(subjects_dir, sub):
181179
wf.connect(vt3, "transformed_file", convert1, "in_file")
182180
wf.connect(convert1, "out_file", datasink, "preafq.anat.@anat")
183181

184-
def reportNodeFunc(dwi_corrected_file, eddy_rms, eddy_report,
182+
def reportNodeFunc(dwi_corrected_file, eddy_rms, eddy_report,
185183
color_fa_file, anat_mask_file):
186184
from preafq.qc import create_report_json
187185

188-
report = create_report_json(dwi_corrected_file, eddy_rms, eddy_report,
189-
color_fa_file, anat_mask_file)
186+
report = create_report_json(dwi_corrected_file, eddy_rms, eddy_report,
187+
color_fa_file, anat_mask_file)
190188
return report
191-
192-
reportNode = pe.Node(niu.Function(input_names=['dwi_corrected_file', 'eddy_rms',
193-
'eddy_report', 'color_fa_file',
194-
'anat_mask_file'],
195-
output_names=['report'],
196-
function=reportNodeFunc),
197-
name="reportJSON")
198-
189+
190+
reportNode = pe.Node(niu.Function(
191+
input_names=['dwi_corrected_file', 'eddy_rms',
192+
'eddy_report', 'color_fa_file',
193+
'anat_mask_file'],
194+
output_names=['report'],
195+
function=reportNodeFunc
196+
), name="reportJSON")
197+
199198
wf.connect(prep, "outputnode.out_file", reportNode, 'dwi_corrected_file')
200199
wf.connect(prep, "fsl_eddy.out_movement_rms", reportNode, 'eddy_rms')
201200
wf.connect(prep, "fsl_eddy.out_outlier_report", reportNode, 'eddy_report')

0 commit comments

Comments
 (0)