Browse Source

Code for the AO vs AV BOLD response comparison

Michael Hanke 8 years ago
parent
commit
c848303042
3 changed files with 436 additions and 0 deletions
  1. 149 0
      code/calc_ao_av_corr
  2. 51 0
      code/calc_global_aoav_corr_map.sh
  3. 236 0
      code/calc_per_run_ao_av_corr.submit

+ 149 - 0
code/calc_ao_av_corr

@@ -0,0 +1,149 @@
+#!/usr/bin/python
+"""
+FILL ME IN
+"""
+
+import os
+import sys
+
+if not len(sys.argv) == 3:
+    print __doc__
+    sys.exit(1)
+
+# subj
+subj = int(sys.argv[1])
+# run
+run = int(sys.argv[2])
+
+from os.path import join as _opj
+import numpy as np
+from scipy.stats import spearmanr, pearsonr
+from mvpa2.base.hdf5 import h5save
+from nilearn.image import smooth_img
+import nibabel as nb
+from mvpa2.mappers.base import ChainMapper
+from mvpa2.mappers.detrend import PolyDetrendMapper
+from mvpa2.mappers.filters import IIRFilterMapper
+from scipy import signal
+from mvpa2.datasets.mri import fmri_dataset
+from mvpa2.datasets.mri import map2nifti
+
+mc_reg_names = ('mc_xtrans', 'mc_ytrans', 'mc_ztrans', 'mc_xrot',
+                'mc_yrot', 'mc_zrot')
+
+# TODO put this into pymvpa
+def preprocessed_fmri_dataset(
+        bold_fname, preproc_img=None, preproc_ds=None, add_sa=None,
+        **kwargs):
+    """
+
+    Parameters
+    ----------
+    bold_fname : str
+      File name of BOLD scan
+    preproc_img : callable or None
+      See get_bold_run_dataset() documentation
+    preproc_ds : callable or None
+      If not None, this callable will be called with each run bold dataset
+      as an argument before ``modelfx`` is executed. The callable must
+      return a dataset.
+    add_sa : dict or None
+
+    Returns
+    -------
+    Dataset
+    """
+    # open the BOLD image
+    bold_img = nb.load(bold_fname)
+
+    if not preproc_img is None:
+        bold_img = preproc_img(bold_img)
+    # load (and mask) data
+    ds = fmri_dataset(bold_img, **kwargs)
+
+    if not add_sa is None:
+        if hasattr(add_sa, 'dtype') and not add_sa.dtype.names is None:
+            # this is a recarray
+            iter_ = add_sa.dtype.names
+        else:
+            # assume dict
+            iter_ = add_sa
+        for sa in iter_:
+            ds.sa[sa] = add_sa[sa]
+
+    if not preproc_ds is None:
+        ds = preproc_ds(ds)
+    return ds
+
+
+def movie_run_ds(subj, run, task, imgspace, **kwargs):
+    if task == 'aomovie':
+        mcfile = \
+            'src/phase1/sub-%.2i/BOLD/task001_run%.3i/bold_dico_moco.txt' \
+            % (subj, run)
+    elif task == 'avmovie':
+        mcfile = \
+            'sub-%.2i/in_%s/sub-%.2i_task-%s_run-%i_bold_mcparams.txt' \
+            % (subj, imgspace, subj, task, run)
+    else:
+        raise ValueError("unknown task '%s'" % task)
+
+    mc = np.recfromtxt(mcfile, names=mc_reg_names)
+
+    ds = preprocessed_fmri_dataset(
+        'sub-%.2i/in_%s/sub-%.2i_task-%s_run-%i_bold.nii.gz'
+        % (subj, imgspace, subj, task, run),
+        add_sa=mc,
+        **kwargs)
+    return ds
+
+def fisher_xfm(arr, n):
+    arr = np.asanyarray(arr)
+    # z-transform
+    z = 0.5 * np.log((1 + arr) / (1 - arr))
+    # standardize to unit variance
+    z = z / (1. / np.sqrt(n - 3))
+    return z
+
+def smooth(img):
+    # we need to preserve the original header because the smoothing function
+    # fucks the TR up
+    nimg = smooth_img(img, fwhm=4.0)
+    return nb.Nifti1Image(nimg.get_data(),
+                          img.get_affine(),
+                          header=img.get_header())
+
+# template files are intensity normalized, >100 should be a good liberal brain
+# mask
+mask = nb.load(
+    'src/tnt/sub-%.2i/bold7Tp1/in_bold3Tp2/brain.nii.gz' % subj).get_data() > 100
+
+# time series pre-processing
+# regress out motion
+pdm = PolyDetrendMapper(0, opt_regs=mc_reg_names, auto_train=True)
+# spectral filter
+sfm = IIRFilterMapper(*signal.butter(8, (0.016, 0.25), btype='bandpass'))
+tspreproc = ChainMapper([pdm, sfm])
+
+aomovie = movie_run_ds(subj, run, 'aomovie','bold3Tp2',
+    mask=mask, preproc_img=smooth, preproc_ds=tspreproc)
+avmovie = movie_run_ds(subj, run, 'avmovie','bold3Tp2',
+    mask=mask, preproc_img=smooth, preproc_ds=tspreproc)
+
+# compute voxelwise correlation between audio and audio-visual data
+sr = np.array(
+    [spearmanr(aomovie.samples[:,i], avmovie.samples[:,i])[0]
+        for i in xrange(aomovie.nfeatures)])
+pr = np.array(
+    [pearsonr(aomovie.samples[:,i], avmovie.samples[:,i])[0]
+        for i in xrange(aomovie.nfeatures)])
+# Fisher transformation to yield normal distribution
+sz = fisher_xfm(sr, len(aomovie))
+pz = fisher_xfm(pr, len(aomovie))
+
+nb.save(map2nifti(aomovie, sz),
+        'sub-%.2i/in_bold3Tp2/sub-%.2i_aoav_run-%i_spearmanZ.nii.gz'
+        % (subj, subj, run))
+nb.save(map2nifti(aomovie, pz),
+        'sub-%.2i/in_bold3Tp2/sub-%.2i_aoav_run-%i_pearsonZ.nii.gz'
+        % (subj, subj, run))

+ 51 - 0
code/calc_global_aoav_corr_map.sh

@@ -0,0 +1,51 @@
+#!/bin/bash
+
+set -e
+set -u
+
+corrtype=$1
+
+odir="qa/bold3Tp2/aoav_corr_${corrtype}"
+mkdir -p $odir
+
+for s in sub-*; do
+  if [ "$s" = "sub-10" ]; then
+    # this subject doesn't have usable 7T data
+    continue
+  fi
+  echo "$s"
+  $FSLDIR/bin/fslmerge -t $odir/${s}_all $s/in_bold3Tp2/${s}_*_${corrtype}Z.nii.gz
+  $FSLDIR/bin/fslmaths $odir/${s}_all -Tmean $odir/${s}_avg
+  $FSLDIR/bin/applywarp \
+    -i $odir/${s}_avg \
+    -r src/tnt/templates/grpbold3Tp2/brain.nii.gz \
+    -o $odir/${s}_avg_grpbold3Tp2 \
+    -w src/tnt/${s}/bold3Tp2/in_grpbold3Tp2/subj2tmpl_warp.nii.gz \
+    --interp=trilinear
+  $FSLDIR/bin/flirt \
+    -in src/tnt/${s}/bold7Tp1/brain_mask.nii.gz \
+    -ref src/tnt/${s}/bold3Tp2/brain.nii.gz \
+    -init src/tnt/${s}/bold7Tp1/in_bold3Tp2/xfm_6dof.mat \
+    -applyxfm \
+    -o $odir/${s}_brain_mask_in3T \
+    -interp nearestneighbour
+  $FSLDIR/bin/applywarp \
+    -i $odir/${s}_brain_mask_in3T \
+    -r src/tnt/templates/grpbold3Tp2/brain.nii.gz \
+    -o $odir/${s}_brain_mask \
+    -w src/tnt/${s}/bold3Tp2/in_grpbold3Tp2/subj2tmpl_warp.nii.gz \
+    --interp=nn
+
+done
+
+$FSLDIR/bin/fslmerge -t $odir/allmask_grpbold3Tp2 $odir/*_brain_mask.nii.gz
+$FSLDIR/bin/fslmaths $odir/allmask_grpbold3Tp2 -Tmean -thr 1 -bin $odir/mask_grpbold3Tp2
+$FSLDIR/bin/fslmerge -t $odir/all_grpbold3Tp2 $odir/*_avg_grpbold3Tp2.nii.gz
+$FSLDIR/bin/fslmaths $odir/all_grpbold3Tp2 -Tmean $odir/avg_grpbold3Tp2
+$FSLDIR/bin/fslmaths $odir/all_grpbold3Tp2 -Tstd $odir/std_grpbold3Tp2
+cd $odir
+$FSLDIR/bin/easythresh avg_grpbold3Tp2.nii.gz mask_grpbold3Tp2 3.1 0.05 \
+	../../../src/tnt/templates/grpbold3Tp2/brain.nii.gz easythresh_31_05
+$FSLDIR/bin/easythresh avg_grpbold3Tp2.nii.gz mask_grpbold3Tp2 2.3 0.05 \
+	../../../src/tnt/templates/grpbold3Tp2/brain.nii.gz easythresh_23_05
+

+ 236 - 0
code/calc_per_run_ao_av_corr.submit

@@ -0,0 +1,236 @@
+universe = vanilla
+output = condor_logs/$(CLUSTER).$(PROCESS).out
+error = condor_logs/$(CLUSTER).$(PROCESS).err
+log = condor_logs/$(CLUSTER).$(PROCESS).log
+initialdir = /home/data/psyinf/forrest_gump/collection/aligned
+getenv = True
+request_cpus = 1
+request_memory = 4000
+should_transfer_files = NO
+transfer_executable = False
+executable = /home/data/psyinf/forrest_gump/collection/aligned/code/calc_ao_av_corr
+
+arguments =  1 1
+queue
+arguments =  1 2
+queue
+arguments =  1 3
+queue
+arguments =  1 4
+queue
+arguments =  1 5
+queue
+arguments =  1 6
+queue
+arguments =  1 7
+queue
+arguments =  1 8
+queue
+arguments =  2 1
+queue
+arguments =  2 2
+queue
+arguments =  2 3
+queue
+arguments =  2 4
+queue
+arguments =  2 5
+queue
+arguments =  2 6
+queue
+arguments =  2 7
+queue
+arguments =  2 8
+queue
+arguments =  3 1
+queue
+arguments =  3 2
+queue
+arguments =  3 3
+queue
+arguments =  3 4
+queue
+arguments =  3 5
+queue
+arguments =  3 6
+queue
+arguments =  3 7
+queue
+arguments =  3 8
+queue
+arguments =  4 1
+queue
+arguments =  4 2
+queue
+arguments =  4 3
+queue
+arguments =  4 4
+queue
+arguments =  4 5
+queue
+arguments =  4 6
+queue
+arguments =  4 7
+queue
+arguments =  4 8
+queue
+arguments =  5 1
+queue
+arguments =  5 2
+queue
+arguments =  5 3
+queue
+arguments =  5 4
+queue
+arguments =  5 5
+queue
+arguments =  5 6
+queue
+arguments =  5 7
+queue
+arguments =  5 8
+queue
+arguments =  6 1
+queue
+arguments =  6 2
+queue
+arguments =  6 3
+queue
+arguments =  6 4
+queue
+arguments =  6 5
+queue
+arguments =  6 6
+queue
+arguments =  6 7
+queue
+arguments =  6 8
+queue
+arguments =  9 1
+queue
+arguments =  9 2
+queue
+arguments =  9 3
+queue
+arguments =  9 4
+queue
+arguments =  9 5
+queue
+arguments =  9 6
+queue
+arguments =  9 7
+queue
+arguments =  9 8
+queue
+arguments = 14 1
+queue
+arguments = 14 2
+queue
+arguments = 14 3
+queue
+arguments = 14 4
+queue
+arguments = 14 5
+queue
+arguments = 14 6
+queue
+arguments = 14 7
+queue
+arguments = 14 8
+queue
+arguments = 15 1
+queue
+arguments = 15 2
+queue
+arguments = 15 3
+queue
+arguments = 15 4
+queue
+arguments = 15 5
+queue
+arguments = 15 6
+queue
+arguments = 15 7
+queue
+arguments = 15 8
+queue
+arguments = 16 1
+queue
+arguments = 16 2
+queue
+arguments = 16 3
+queue
+arguments = 16 4
+queue
+arguments = 16 5
+queue
+arguments = 16 6
+queue
+arguments = 16 7
+queue
+arguments = 16 8
+queue
+arguments = 17 1
+queue
+arguments = 17 2
+queue
+arguments = 17 3
+queue
+arguments = 17 4
+queue
+arguments = 17 5
+queue
+arguments = 17 6
+queue
+arguments = 17 7
+queue
+arguments = 17 8
+queue
+arguments = 18 1
+queue
+arguments = 18 2
+queue
+arguments = 18 3
+queue
+arguments = 18 4
+queue
+arguments = 18 5
+queue
+arguments = 18 6
+queue
+arguments = 18 7
+queue
+arguments = 18 8
+queue
+arguments = 19 1
+queue
+arguments = 19 2
+queue
+arguments = 19 3
+queue
+arguments = 19 4
+queue
+arguments = 19 5
+queue
+arguments = 19 6
+queue
+arguments = 19 7
+queue
+arguments = 19 8
+queue
+arguments = 20 1
+queue
+arguments = 20 2
+queue
+arguments = 20 3
+queue
+arguments = 20 4
+queue
+arguments = 20 5
+queue
+arguments = 20 6
+queue
+arguments = 20 7
+queue
+arguments = 20 8
+queue