Skip to content

Commit 4087d23

Browse files
committed
Merge pull request #16 from akeshavan/master
fix: QA and correlation matrix saved
2 parents 5cac647 + 0d0cbb8 commit 4087d23

7 files changed

+132
-29
lines changed

fmri/qa/QA_fmri.py

+28-20
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from nipype.interfaces import fsl
1515
#from nipype.utils.config import config
1616
#config.enable_debug_mode()
17-
from QA_utils import plot_ADnorm, tsdiffana, tsnr_roi, combine_table, art_output, plot_motion
17+
from QA_utils import plot_ADnorm, tsdiffana, tsnr_roi, combine_table, art_output, plot_motion, plot_ribbon, plot_anat
1818
import sys
1919
sys.path.insert(0,'../../utils/')
2020
from reportsink.io import ReportSink
@@ -45,6 +45,7 @@ def preproc_datagrabber(name='preproc_datagrabber'):
4545
name = name)
4646
datasource.inputs.base_directory = os.path.join(c.sink_dir,'analyses','func')
4747
datasource.inputs.template ='*'
48+
datasource.sort_filelist = True
4849
datasource.inputs.field_template = dict(motion_parameters='%s/preproc/motion/*.par',
4950
outlier_files='%s/preproc/art/*_outliers.txt',
5051
art_norm='%s/preproc/art/norm.*.txt',
@@ -268,11 +269,24 @@ def QA_workflow(name='QA'):
268269
name='tsdiffana', iterfield=["img"])
269270

270271
art_info = pe.MapNode(util.Function(input_names = ['art_file'],
271-
output_names = ['table'],
272+
output_names = ['table','out'],
272273
function=art_output),
273274
name='art_output', iterfield=["art_file"])
274275

275276
fssource = pe.Node(interface = FreeSurferSource(),name='fssource')
277+
278+
plotribbon = pe.Node(util.Function(input_names=['Brain'],
279+
output_names=['images'],
280+
function=plot_ribbon),
281+
name="plot_ribbon")
282+
283+
workflow.connect(fssource, 'ribbon', plotribbon, 'Brain')
284+
285+
286+
plotanat = pe.Node(util.Function(input_names=['brain'],
287+
output_names=['images'],
288+
function=plot_anat),
289+
name="plot_anat")
276290

277291
roidevplot = tsnr_roi(plot=False,name='tsnr_stddev_roi',roi=['all'])
278292
roidevplot.inputs.inputspec.TR = c.TR
@@ -285,6 +299,7 @@ def QA_workflow(name='QA'):
285299
workflow.connect(infosource, 'subject_id', roidevplot, 'inputspec.subject')
286300
workflow.connect(infosource, 'subject_id', roisnrplot, 'inputspec.subject')
287301

302+
288303
tablecombine = pe.MapNode(util.Function(input_names = ['roidev',
289304
'roisnr'],
290305
output_names = ['roisnr'],
@@ -293,12 +308,12 @@ def QA_workflow(name='QA'):
293308

294309

295310

296-
adnormplot = pe.MapNode(util.Function(input_names = ['ADnorm','TR'],
311+
adnormplot = pe.MapNode(util.Function(input_names = ['ADnorm','TR','norm_thresh','out'],
297312
output_names = ['plot'],
298313
function=plot_ADnorm),
299-
name='ADnormplot', iterfield=['ADnorm'])
300-
301-
314+
name='ADnormplot', iterfield=['ADnorm','out'])
315+
adnormplot.inputs.norm_thresh = c.norm_thresh
316+
workflow.connect(art_info,'out',adnormplot,'out')
302317

303318
convert = pe.Node(interface=fs.MRIConvert(),name='converter')
304319

@@ -315,24 +330,17 @@ def QA_workflow(name='QA'):
315330
name='overlay_mask')
316331
overlaymask.inputs.threshold = 0
317332

318-
#overlaymask = pe.Node(interface=fsl.Overlay(),name='fsl_overlaymask')
319-
#overlaymask.inputs.transparency = True
320-
#overlaymask.inputs.stat_thresh = (0,1)
321-
#overlaymask.inputs.full_bg_range= True
322-
323-
#slicermask = pe.Node(interface=fsl.Slicer(),name='slicer_mask')
324-
#slicermask.inputs.all_axial = True
325-
#slicermask.inputs.image_width = 4
326333

327-
workflow.connect(datagrabber, 'mask', overlaymask, 'background_image')
328-
workflow.connect(datagrabber, 'mean_image', overlaymask, 'stat_image')
334+
#workflow.connect(datagrabber, 'mask', overlaymask, 'background_image')
335+
workflow.connect(datagrabber, 'mean_image', plotanat, 'brain')
329336
#workflow.connect(overlaymask,'out_file', slicermask, 'in_file')
330337

331338
write_rep = pe.Node(interface=ReportSink(orderfields=['Introduction',
332339
'in_file',
333340
'config_params',
334341
'Art_Detect',
335-
'Brain_Mask_and_Mean_Functional',
342+
'Mean_Functional',
343+
'Ribbon',
336344
'motion_plots',
337345
'tsdiffana',
338346
'ADnorm',
@@ -344,7 +352,7 @@ def QA_workflow(name='QA'):
344352
write_rep.inputs.report_name = "Preprocessing_Report"
345353
write_rep.inputs.json_sink = c.json_sink
346354
workflow.connect(infosource,'subject_id',write_rep,'container')
347-
workflow.connect(overlaymask, 'fnames', write_rep, "Brain_Mask_and_Mean_Functional")
355+
workflow.connect(plotanat, 'images', write_rep, "Mean_Functional")
348356
#workflow.connect(slicermask,'out_file', write_rep, "Brain_Mask_and_Mean_Functional")
349357

350358
# Define Inputs
@@ -376,7 +384,7 @@ def QA_workflow(name='QA'):
376384
workflow.connect(convert,'out_file',voltransform,'target_file')
377385
workflow.connect(inputspec,'reg_file',voltransform,'reg_file')
378386
workflow.connect(inputspec,'tsnr',voltransform, 'source_file')
379-
387+
workflow.connect(plotribbon, 'images', write_rep, 'Ribbon')
380388
workflow.connect(voltransform,'transformed_file', overlaynew,'stat_image')
381389
workflow.connect(convert,'out_file', overlaynew,'background_image')
382390

@@ -403,7 +411,7 @@ def QA_workflow(name='QA'):
403411
a.base_dir = c.working_dir
404412
a.write_graph()
405413
a.inputs.inputspec.config_params = start_config_table()
406-
414+
a.config = {'execution' : {'crashdump_dir' : c.crash_dir}}
407415
if c.run_on_grid:
408416
a.run(plugin=c.plugin,plugin_args=c.plugin_args)
409417
else:

fmri/qa/QA_utils.py

+76-4
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ def art_output(art_file):
1818
except:
1919
out=np.asarray([])
2020
table=[["file",art_file],["num outliers", str(out.shape)],["timepoints",str(out)]]
21-
return table
21+
return table, [out]
2222

2323

24-
def plot_ADnorm(ADnorm,TR):
24+
def plot_ADnorm(ADnorm,TR,norm_thresh,out):
2525
""" Returns a plot of the composite_norm file output from art
2626
2727
Parameters
@@ -41,7 +41,7 @@ def plot_ADnorm(ADnorm,TR):
4141
import matplotlib.pyplot as plt
4242
import os
4343
import numpy as np
44-
44+
out = out[0]
4545
plot = os.path.abspath('plot_'+os.path.split(ADnorm)[1]+'.png')
4646

4747
data = np.genfromtxt(ADnorm)
@@ -50,7 +50,19 @@ def plot_ADnorm(ADnorm,TR):
5050
plt.plot(X,data)
5151
plt.xlabel('Time (s)')
5252
plt.ylabel('Composite Norm')
53-
plt.savefig(plot)
53+
54+
if norm_thresh > max(data):
55+
plt.axis([0,TR*data.shape[0],0,norm_thresh*1.1])
56+
plt.plot(X,np.ones(X.shape)*norm_thresh)
57+
for o in out:
58+
plt.plot(o*TR*np.ones(2),[0,norm_thresh*1.1],'r-')
59+
else:
60+
plt.axis([0,TR*data.shape[0],0,max(data)*1.1])
61+
plt.plot(X,np.ones(X.shape)*norm_thresh)
62+
for o in out:
63+
plt.plot(o*TR*np.ones(2),[0,max(data)*1.1],'r-')
64+
65+
plt.savefig(plot,bbox_inches='tight')
5466
plt.close()
5567
return plot
5668

@@ -275,6 +287,7 @@ def plot_motion(motion_parameters):
275287
fname_t=os.path.abspath('translations.png')
276288
plt.figure(1,figsize = (8,3))
277289
plt.plot(np.genfromtxt(motion_parameters)[:,3:])
290+
plt.legend(['x','y','z'])
278291
plt.title("Estimated Translations (mm)")
279292
plt.savefig(fname_t)
280293
plt.close()
@@ -283,8 +296,67 @@ def plot_motion(motion_parameters):
283296
plt.figure(2,figsize = (8,3))
284297
plt.plot(np.genfromtxt(motion_parameters)[:,:3])
285298
plt.title("Estimated Rotations (rad)")
299+
plt.legend(['roll','pitch','yaw'])
286300
plt.savefig(fname_r)
287301
plt.close()
288302
fname = [fname_t, fname_r]
289303
return fname
290304

305+
def plot_ribbon(Brain):
306+
import os.path
307+
import pylab as pl
308+
from nibabel import load
309+
from nipy.labs import viz
310+
images = []
311+
312+
for brain in Brain:
313+
if os.path.split(brain)[1] == 'ribbon.mgz':
314+
img = load(brain)
315+
data = img.get_data()*100
316+
affine = img.get_affine()
317+
viz.plot_anat(anat=data, anat_affine=affine, draw_cross=False, slicer='x', cmap=viz.cm.black_green)
318+
319+
x_view = os.path.abspath('x_view.png')
320+
y_view = os.path.abspath('y_view.png')
321+
z_view = os.path.abspath('z_view.png')
322+
323+
pl.savefig(x_view,bbox_inches='tight')
324+
325+
viz.plot_anat(anat=data, anat_affine=affine, draw_cross=False, slicer='y', cmap=viz.cm.black_green)
326+
pl.savefig(y_view,bbox_inches='tight')
327+
328+
viz.plot_anat(anat=data, anat_affine=affine, draw_cross=False, slicer='z', cmap=viz.cm.black_green)
329+
pl.savefig(z_view,bbox_inches='tight')
330+
331+
images = [x_view, y_view, z_view]
332+
pl.close()
333+
return images
334+
335+
def plot_anat(brain):
336+
import os.path
337+
import pylab as pl
338+
from nibabel import load
339+
from nipy.labs import viz
340+
341+
img = load(brain)
342+
data = img.get_data()
343+
affine = img.get_affine()
344+
viz.plot_anat(anat=data, anat_affine=affine, draw_cross=False, slicer='x')
345+
346+
x_view = os.path.abspath('x_view.png')
347+
y_view = os.path.abspath('y_view.png')
348+
z_view = os.path.abspath('z_view.png')
349+
350+
pl.savefig(x_view,bbox_inches='tight')
351+
352+
viz.plot_anat(anat=data, anat_affine=affine, draw_cross=False, slicer='y')
353+
pl.savefig(y_view,bbox_inches='tight')
354+
355+
viz.plot_anat(anat=data, anat_affine=affine, draw_cross=False, slicer='z')
356+
pl.savefig(z_view,bbox_inches='tight')
357+
358+
images = [x_view, y_view, z_view]
359+
pl.close()
360+
return images
361+
362+

fmri/qa/resting_QA.py

+21-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ def corr_image(resting_image,fwhm):
4040
img = nb.load(resting_image)
4141
corrmat = np.corrcoef(np.squeeze(img.get_data()))
4242
corrmat[np.isnan(corrmat)] = 0
43+
corrmat_npz = os.path.abspath('corrmat.npz')
44+
np.savez(corrmat_npz,corrmat=corrmat)
45+
4346
br = Brain('fsaverage5', 'lh', 'smoothwm')
4447

4548
#br.add_overlay(corrmat[0,:], min=0.2, name=0, visible=True)
@@ -59,7 +62,7 @@ def corr_image(resting_image,fwhm):
5962

6063
#br.add_overlay(precuneus[0,1:], min=0.3, sign='pos', name='mean', visible=True)
6164

62-
br.add_overlay(precuneus[0,1:], min=0.2, name='mean', visible=True)
65+
br.add_overlay(precuneus[0,1:], name='mean', visible=True)
6366
plt.hist(precuneus[0,1:], 128)
6467
plt.savefig(os.path.abspath("histogram.png"))
6568
plt.close()
@@ -80,7 +83,7 @@ def corr_image(resting_image,fwhm):
8083
roitable=[roitable]
8184
histogram = os.path.abspath("histogram.png")
8285

83-
return corr_image, ims, roitable, histogram
86+
return corr_image, ims, roitable, histogram, corrmat_npz
8487

8588
def vol2surf(input_volume,ref_volume,reg_file,trg,hemi):
8689
import os
@@ -149,7 +152,7 @@ def resting_QA(name="resting_QA"):
149152
workflow.connect(inputspec,'mean_image', tosurf,'ref_volume')
150153

151154
to_img = pe.MapNode(util.Function(input_names=['resting_image','fwhm'],
152-
output_names=["corr_image","ims","roitable","histogram"],function=corr_image),
155+
output_names=["corr_image","ims","roitable","histogram","corrmat_npz"],function=corr_image),
153156
name="image_gen",iterfield=["resting_image"])
154157

155158
workflow.connect(tosurf,'out_file',to_img,'resting_image')
@@ -161,6 +164,21 @@ def resting_QA(name="resting_QA"):
161164
sink.inputs.json_sink = c.json_sink
162165
sink.inputs.Introduction = "Resting state corellations with seed at precuneus"
163166
sink.inputs.Configuration = start_config_table()
167+
168+
corrmat_sinker = pe.Node(nio.DataSink(),name='corrmat_sink')
169+
corrmat_sinker.inputs.base_directory = c.json_sink
170+
171+
def get_substitutions(subject_id):
172+
subs = [('_fwhm_','fwhm'),('_subject_id_%s'%subject_id,'')]
173+
for i in range(20):
174+
subs.append(('_image_gen%d/corrmat.npz'%i,'corrmat%02d.npz'%i))
175+
return subs
176+
177+
#corrmat_sinker.inputs.substitutions = #[('_fwhm_','fwhm'),('_subject_id_%s',''),('_image_gen%s','')]
178+
workflow.connect(infosource,('subject_id',get_substitutions),corrmat_sinker,'substitutions')
179+
workflow.connect(infosource,'subject_id',corrmat_sinker,'container')
180+
workflow.connect(to_img,'corrmat_npz',corrmat_sinker,'corrmats')
181+
164182
#sink.inputs.report_name = "Resting_State_Correlations"
165183
workflow.connect(infosource,'subject_id',sink,'Subject')
166184
workflow.connect(fwhmsource,('fwhm',addtitle),sink,'report_name')

fmri/resting/resting_preproc.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ def prep_workflow(subjects, fieldmap):
143143
#realign.inputs.loops = 2
144144
realign.inputs.speedup = 10
145145
realign.plugin_args = {'qsub_args': '-l nodes=1:ppn=3'}
146-
146+
preprocess.config = {'execution' : {'crashdump_dir' : c.crash_dir}}
147147
if len(c.subjects) == 1:
148148
preprocess.write_graph(graph2use='exec',
149149
dotfilename='single_subject_exec.dot')

fmri/resting/sad_resting_config.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@
113113
'SAD_POST46','SAD_POST47','SAD_POST50','SAD_POST51',
114114
'SAD_POST52','SAD_POST53','SAD_POST54','SAD_POST56',
115115
'SAD_POST58']
116-
subjects = controls+patients+tp2s
116+
subjects = patients+tp2s
117+
#['SAD_POST06','SAD2_036','SAD_POST07','SAD_POST46','SAD_023','SAD_018','SAD_POST52','SAD_P57',
118+
# 'SAD_POST50','SAD_P12','SAD2_022','SAD_POST54','SAD2_050','SAD_P43','SAD_024','SAD_POST10',
119+
# 'SAD_POST13','SAD_POST05','SAD_POST44','SAD2_044'] #These people had errors
117120

118121
run_on_grid = True
119122

fmri/task/first_level.py

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ def getsubs(subject_id,getcontrasts,subjectinfo,fwhm):
229229
c = __import__(fname.split('.')[0])
230230

231231
first_level = combine_wkflw(c)
232+
first_level.config = {'execution' : {'crashdump_dir' : c.crash_dir}}
232233
#first_level.write_graph()
233234
if run_on_grid:
234235
first_level.run(plugin='PBS', plugin_args = c.plugin_args)

fmri/task/preproc.py

+1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ def prep_workflow(subjects,fieldmap):
143143
realign.inputs.speedup = 15
144144
cc = preprocess.get_node('preproc.CompCor')
145145
cc.plugin_args = {'qsub_args': '-l nodes=1:ppn=3'}
146+
preprocess.config = {'execution' : {'crashdump_dir' : c.crash_dir}}
146147
if c.run_on_grid:
147148
preprocess.run(plugin=c.plugin,plugin_args = c.plugin_args)
148149
else:

0 commit comments

Comments
 (0)