rpipe 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +23 -0
- data/LICENSE +20 -0
- data/README +0 -0
- data/README.rdoc +33 -0
- data/Rakefile +78 -0
- data/VERSION +1 -0
- data/bin/create_driver.rb +79 -0
- data/bin/rpipe +131 -0
- data/bin/swallow_batch_run.rb +21 -0
- data/lib/core_additions.rb +5 -0
- data/lib/custom_methods/JohnsonMerit220Visit1Preproc.m +26 -0
- data/lib/custom_methods/JohnsonMerit220Visit1Preproc.rb +43 -0
- data/lib/custom_methods/JohnsonMerit220Visit1Preproc_job.m +80 -0
- data/lib/custom_methods/JohnsonMerit220Visit1Stats.m +74 -0
- data/lib/custom_methods/JohnsonMerit220Visit1Stats.rb +63 -0
- data/lib/custom_methods/JohnsonMerit220Visit1Stats_job.m +63 -0
- data/lib/custom_methods/JohnsonTbiLongitudinalSnodPreproc.m +26 -0
- data/lib/custom_methods/JohnsonTbiLongitudinalSnodPreproc.rb +41 -0
- data/lib/custom_methods/JohnsonTbiLongitudinalSnodPreproc_job.m +69 -0
- data/lib/custom_methods/JohnsonTbiLongitudinalSnodStats.m +76 -0
- data/lib/custom_methods/JohnsonTbiLongitudinalSnodStats.rb +67 -0
- data/lib/custom_methods/JohnsonTbiLongitudinalSnodStats_job.m +59 -0
- data/lib/custom_methods/ReconWithHello.rb +7 -0
- data/lib/default_logger.rb +13 -0
- data/lib/default_methods/default_preproc.rb +76 -0
- data/lib/default_methods/default_recon.rb +80 -0
- data/lib/default_methods/default_stats.rb +94 -0
- data/lib/default_methods/recon/physionoise_helper.rb +69 -0
- data/lib/default_methods/recon/raw_sequence.rb +109 -0
- data/lib/generators/job_generator.rb +36 -0
- data/lib/generators/preproc_job_generator.rb +31 -0
- data/lib/generators/recon_job_generator.rb +76 -0
- data/lib/generators/stats_job_generator.rb +70 -0
- data/lib/generators/workflow_generator.rb +128 -0
- data/lib/global_additions.rb +18 -0
- data/lib/logfile.rb +310 -0
- data/lib/matlab_helpers/CreateFunctionalVolumeStruct.m +6 -0
- data/lib/matlab_helpers/import_csv.m +32 -0
- data/lib/matlab_helpers/matlab_queue.rb +37 -0
- data/lib/matlab_helpers/prepare_onsets_xls.m +30 -0
- data/lib/rpipe.rb +254 -0
- data/rpipe.gemspec +177 -0
- data/spec/generators/preproc_job_generator_spec.rb +27 -0
- data/spec/generators/recon_job_generator_spec.rb +33 -0
- data/spec/generators/stats_job_generator_spec.rb +50 -0
- data/spec/generators/workflow_generator_spec.rb +97 -0
- data/spec/helper_spec.rb +40 -0
- data/spec/integration/johnson.merit220.visit1_spec.rb +47 -0
- data/spec/integration/johnson.tbi.longitudinal.snod_spec.rb +48 -0
- data/spec/logfile_spec.rb +96 -0
- data/spec/matlab_queue_spec.rb +40 -0
- data/spec/merit220_stats_spec.rb +81 -0
- data/spec/physio_spec.rb +98 -0
- data/test/drivers/merit220_workflow_sample.yml +15 -0
- data/test/drivers/mrt00000.yml +65 -0
- data/test/drivers/mrt00015.yml +62 -0
- data/test/drivers/mrt00015_hello.yml +41 -0
- data/test/drivers/mrt00015_withphys.yml +81 -0
- data/test/drivers/tbi000.yml +129 -0
- data/test/drivers/tbi000_separatevisits.yml +137 -0
- data/test/drivers/tmp.yml +58 -0
- data/test/fixtures/faces3_recognitionA.mat +0 -0
- data/test/fixtures/faces3_recognitionA.txt +86 -0
- data/test/fixtures/faces3_recognitionA_equal.csv +25 -0
- data/test/fixtures/faces3_recognitionA_unequal.csv +21 -0
- data/test/fixtures/faces3_recognitionB_incmisses.txt +86 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CPd3R_40.txt +13360 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CPd3_40.txt +13360 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CPttl_40.txt +13360 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CRTd3R_40.txt +13360 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CRTd3_40.txt +13360 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CRTttl_40.txt +13360 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_CRTd3R_40.txt +334 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_CRTd3_40.txt +334 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_CRTttl_40.txt +334 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_RRT_40.txt +334 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_RVT_40.txt +334 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_card_spline_40.txt +334 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_resp_spline_40.txt +334 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_RRT_40.txt +9106 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_RVT_40.txt +9106 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_CRTd3R_40.txt +167 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_CRTd3_40.txt +167 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_CRTttl_40.txt +167 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_RRT_40.txt +167 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_RVT_40.txt +167 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_card_spline_40.txt +167 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_resp_spline_40.txt +167 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_card_spline_40.txt +13360 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_resp_spline_40.txt +9106 -0
- data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_resp_spline_downsampled_40.txt +9106 -0
- data/test/fixtures/ruport_summary.yml +123 -0
- data/test/fixtures/valid_scans.yaml +35 -0
- data/test/helper.rb +10 -0
- data/test/test_dynamic_method_inclusion.rb +10 -0
- data/test/test_includes.rb +11 -0
- data/test/test_integrative_johnson.merit220.visit1.rb +31 -0
- data/test/test_preproc.rb +11 -0
- data/test/test_recon.rb +11 -0
- data/test/test_rpipe.rb +19 -0
- data/vendor/output_catcher.rb +93 -0
- data/vendor/trollop.rb +781 -0
- metadata +260 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'logfile'
|
2
|
+
module JohnsonMerit220Visit1Stats
|
3
|
+
|
4
|
+
DEFAULT_CONDITIONS = [:new_correct_, :new_incorrect_, :old_correct_, :old_incorrect, {:misses => [:new_misses, :old_misses]} ]
|
5
|
+
|
6
|
+
# runs the complete set of tasks using data in a subject's "proc" directory and a preconfigured template spm job.
|
7
|
+
def run_first_level_stats
|
8
|
+
flash "Highway to the dangerzone..."
|
9
|
+
setup_directory(@statsdir, "STATS")
|
10
|
+
|
11
|
+
Dir.chdir(@statsdir) do
|
12
|
+
link_files_from_proc_directory(File.join(@procdir, "sw*.nii"), File.join(@procdir, "rp*.txt"))
|
13
|
+
setup_onsets
|
14
|
+
run_stats_spm_job
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method :perform, :run_first_level_stats
|
19
|
+
|
20
|
+
def setup_onsets
|
21
|
+
setup_conditions
|
22
|
+
create_or_link_onsets_files
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup_conditions
|
26
|
+
@conditions = @conditions ? @conditions.collect! {|c| c.to_sym if c.respond_to? :to_sym } : DEFAULT_CONDITIONS
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_or_link_onsets_files
|
30
|
+
if @onsetsfiles.nil?
|
31
|
+
if @responses.nil?
|
32
|
+
raise ScriptError, "Condition vectors cannot be created because neither log response files nor onsets mat files have been specified."
|
33
|
+
else
|
34
|
+
@onsetsfiles = create_onsets_files(@responses, conditions)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
link_onsets_files
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Finally runs the stats job
|
42
|
+
def run_stats_spm_job
|
43
|
+
images = Dir.glob(File.join(@statsdir, "sw*#{@subid}*[Tt]ask*.nii"))
|
44
|
+
raise ScriptError, "Can't find any smoothed, warped images in #{@statsdir}" if images.empty?
|
45
|
+
|
46
|
+
queue = MatlabQueue.new
|
47
|
+
queue.paths << ['/Applications/spm/spm8/spm8_current',
|
48
|
+
'/apps/spm/spm8_current',
|
49
|
+
File.join(@libdir, 'custom_methods'),
|
50
|
+
File.join(@libdir, 'matlab_helpers') ]
|
51
|
+
|
52
|
+
queue << "#{@method}('#{@statsdir}/', \
|
53
|
+
{ #{images.collect {|im| "'#{File.basename(im)}'"}.join(' ')} }, \
|
54
|
+
{ #{@bold_reps.join(' ') } }, \
|
55
|
+
{ #{@onsetsfiles.collect { |file| "'#{File.basename(file)}'"}.join(' ') } }, \
|
56
|
+
{ #{@regressorsfiles.collect { |file| "'#{File.basename(file)}'"}.join(' ') } }, \
|
57
|
+
'#{@method}_job.m')"
|
58
|
+
|
59
|
+
# puts queue.to_s
|
60
|
+
queue.run!
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
%-----------------------------------------------------------------------
|
2
|
+
% Job configuration created by cfg_util (rev $Rev: 3599 $)
|
3
|
+
%-----------------------------------------------------------------------
|
4
|
+
%% Specification
|
5
|
+
matlabbatch{1}.spm.stats.fmri_spec.dir = '<UNDEFINED>';
|
6
|
+
matlabbatch{1}.spm.stats.fmri_spec.timing.units = 'scans';
|
7
|
+
matlabbatch{1}.spm.stats.fmri_spec.timing.RT = 2;
|
8
|
+
matlabbatch{1}.spm.stats.fmri_spec.timing.fmri_t = 16;
|
9
|
+
matlabbatch{1}.spm.stats.fmri_spec.timing.fmri_t0 = 1;
|
10
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(1).scans = '<UNDEFINED>';
|
11
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(1).cond = struct('name', {}, 'onset', {}, 'duration', {}, 'tmod', {}, 'pmod', {});
|
12
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(1).multi = '<UNDEFINED>';
|
13
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(1).regress = struct('name', {}, 'val', {});
|
14
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(1).multi_reg = '<UNDEFINED>';
|
15
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(1).hpf = 128;
|
16
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(2).scans = '<UNDEFINED>';
|
17
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(2).cond = struct('name', {}, 'onset', {}, 'duration', {}, 'tmod', {}, 'pmod', {});
|
18
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(2).multi = '<UNDEFINED>';
|
19
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(2).regress = struct('name', {}, 'val', {});
|
20
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(2).multi_reg = '<UNDEFINED>';
|
21
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(2).hpf = 128;
|
22
|
+
matlabbatch{1}.spm.stats.fmri_spec.fact = struct('name', {}, 'levels', {});
|
23
|
+
matlabbatch{1}.spm.stats.fmri_spec.bases.hrf.derivs = [0 0];
|
24
|
+
matlabbatch{1}.spm.stats.fmri_spec.volt = 1;
|
25
|
+
matlabbatch{1}.spm.stats.fmri_spec.global = 'None';
|
26
|
+
matlabbatch{1}.spm.stats.fmri_spec.mask = {''};
|
27
|
+
matlabbatch{1}.spm.stats.fmri_spec.cvi = 'AR(1)';
|
28
|
+
%% Estimation
|
29
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1) = cfg_dep;
|
30
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).tname = 'Select SPM.mat';
|
31
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).tgt_spec{1}(1).name = 'filter';
|
32
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).tgt_spec{1}(1).value = 'mat';
|
33
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).tgt_spec{1}(2).name = 'strtype';
|
34
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).tgt_spec{1}(2).value = 'e';
|
35
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).sname = 'fMRI model specification: SPM.mat File';
|
36
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
37
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).src_output = substruct('.','spmmat');
|
38
|
+
matlabbatch{2}.spm.stats.fmri_est.method.Classical = 1;
|
39
|
+
%% Contrast Creation
|
40
|
+
matlabbatch{3}.spm.stats.con.spmmat(1) = cfg_dep;
|
41
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).tname = 'Select SPM.mat';
|
42
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).tgt_spec{1}(1).name = 'filter';
|
43
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).tgt_spec{1}(1).value = 'mat';
|
44
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).tgt_spec{1}(2).name = 'strtype';
|
45
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).tgt_spec{1}(2).value = 'e';
|
46
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).sname = 'Model estimation: SPM.mat File';
|
47
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
48
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).src_output = substruct('.','spmmat');
|
49
|
+
matlabbatch{3}.spm.stats.con.consess{1}.fcon.name = '<UNDEFINED>';
|
50
|
+
matlabbatch{3}.spm.stats.con.consess{1}.fcon.convec{1} = '<UNDEFINED>';
|
51
|
+
matlabbatch{3}.spm.stats.con.consess{1}.fcon.sessrep = 'repl';
|
52
|
+
matlabbatch{3}.spm.stats.con.consess{2}.tcon.name = '<UNDEFINED>';
|
53
|
+
matlabbatch{3}.spm.stats.con.consess{2}.tcon.convec = '<UNDEFINED>';
|
54
|
+
matlabbatch{3}.spm.stats.con.consess{2}.tcon.sessrep = 'repl';
|
55
|
+
matlabbatch{3}.spm.stats.con.consess{3}.tcon.name = '<UNDEFINED>';
|
56
|
+
matlabbatch{3}.spm.stats.con.consess{3}.tcon.convec = '<UNDEFINED>';
|
57
|
+
matlabbatch{3}.spm.stats.con.consess{3}.tcon.sessrep = 'repl';
|
58
|
+
matlabbatch{3}.spm.stats.con.delete = 0;
|
59
|
+
|
60
|
+
% NOTE! F-contrasts expect cells containing contrast arrays, while
|
61
|
+
% T-contrasts expect the arrays themslves (hence the cell reference in
|
62
|
+
% F-contrast definition (convec{1} = [];) but not in T-contrast definition
|
63
|
+
% (convec = [];)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
function [] = JohnsonTbiLongitudinalSnodPreproc(studypath, images, image_boldreps, job_mfile)
|
2
|
+
% [] = Calls and runs TBI Longitudinal preproc job.
|
3
|
+
% merit_preproc('/private/tmp/mrt00015_orig/', ...
|
4
|
+
% {'amrt00015_task1.nii' 'amrt00015_task2.nii' 'amrt00015_rest.nii'}, ...
|
5
|
+
% {164 164 164}, ...
|
6
|
+
% '/private/tmp/mrt00015_orig/mrt00015_preproc_job.m')
|
7
|
+
%
|
8
|
+
|
9
|
+
spm('defaults', 'FMRI');
|
10
|
+
|
11
|
+
% List of open inputs
|
12
|
+
% Realign: Estimate: Session - cfg_files
|
13
|
+
% Realign: Estimate: Session - cfg_files
|
14
|
+
% Realign: Estimate: Session - cfg_files
|
15
|
+
nrun = 1; % enter the number of runs here
|
16
|
+
jobfile = {job_mfile};
|
17
|
+
jobs = repmat(jobfile, 1, nrun);
|
18
|
+
inputs = cell(3, nrun);
|
19
|
+
|
20
|
+
for crun = 1:nrun
|
21
|
+
for index = 1:length(images)
|
22
|
+
inputs{index, crun} = CreateFunctionalVolumeStruct(studypath, images{index}, image_boldreps{index}); % Realign: Estimate: Session - cfg_files
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
spm_jobman('serial', jobs, '', inputs{:});
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'matlab_helpers/matlab_queue'
|
2
|
+
module JohnsonTbiLongitudinalSnodPreproc
|
3
|
+
|
4
|
+
# Runs the preprocessing job, including spm job customization, run spm job, and handling motion issues.
|
5
|
+
# This function assumes a destination directory is set up; it will overwrite preexisting data. Careful!
|
6
|
+
def preproc_visit
|
7
|
+
flash "Spatial Preprocessing Subject: #{@subid}"
|
8
|
+
setup_directory(@procdir, "PREPROC")
|
9
|
+
|
10
|
+
Dir.chdir(@procdir) do
|
11
|
+
link_files_into_proc
|
12
|
+
run_preproc_mfile
|
13
|
+
deal_with_motion
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
alias_method :perform, :preproc_visit
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def run_preproc_mfile
|
22
|
+
images = @scan_labels ? @scan_labels.collect! { |label| Dir.glob("a*#{label}*.nii").to_s } : Dir.glob(File.join(@origdir, "a*#{@subid}*.nii"))
|
23
|
+
|
24
|
+
raise ScriptError, "Can't find any slice-time corrected images in #{@origdir}" if images.empty?
|
25
|
+
queue = MatlabQueue.new
|
26
|
+
queue.paths << ['/Applications/spm/spm8/spm8_current',
|
27
|
+
'/apps/spm/spm8_current',
|
28
|
+
File.join(@libdir, 'custom_methods'),
|
29
|
+
File.join(@libdir, 'matlab_helpers')
|
30
|
+
]
|
31
|
+
|
32
|
+
queue << "JohnsonTbiLongitudinalSnodPreproc('#{@procdir}/', \
|
33
|
+
{ #{images.collect {|im| "'#{File.basename(im)}'"}.join(' ')} }, \
|
34
|
+
{ #{@bold_reps.join(' ') } }, \
|
35
|
+
'JohnsonTbiLongitudinalSnodPreproc_job.m')"
|
36
|
+
|
37
|
+
puts queue.to_s
|
38
|
+
queue.run!
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
%-----------------------------------------------------------------------------
|
2
|
+
% Unfortunately, there is no easy way to pass in the number of images to this
|
3
|
+
% template job, short of writing a function to build one on the fly. Number of
|
4
|
+
% sessions is hardcoded.
|
5
|
+
nsessions = 6;
|
6
|
+
%-----------------------------------------------------------------------------
|
7
|
+
|
8
|
+
%-----------------------------------------------------------------------
|
9
|
+
% Job configuration created by cfg_util (rev $Rev: 3599 $)
|
10
|
+
%-----------------------------------------------------------------------
|
11
|
+
for i = 1:nsessions
|
12
|
+
matlabbatch{1}.spm.spatial.realign.estimate.data{i} = '<UNDEFINED>';
|
13
|
+
end
|
14
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.quality = 0.9;
|
15
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.sep = 4;
|
16
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.fwhm = 5;
|
17
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.rtm = 1;
|
18
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.interp = 2;
|
19
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.wrap = [0 0 0];
|
20
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.weight = {''};
|
21
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1) = cfg_dep;
|
22
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).tname = 'Source Image';
|
23
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).tgt_spec{1}(1).name = 'filter';
|
24
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).tgt_spec{1}(1).value = 'image';
|
25
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).tgt_spec{1}(2).name = 'strtype';
|
26
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).tgt_spec{1}(2).value = 'e';
|
27
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).sname = 'Realign: Estimate: Realigned Images (Sess 1)';
|
28
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
29
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).src_output = substruct('.','sess', '()',{1}, '.','cfiles');
|
30
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.wtsrc = '';
|
31
|
+
for i = 1:nsessions
|
32
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(i) = cfg_dep;
|
33
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(i).tname = 'Images to Write';
|
34
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(i).tgt_spec{1}(1).name = 'filter';
|
35
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(i).tgt_spec{1}(1).value = 'image';
|
36
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(i).tgt_spec{1}(2).name = 'strtype';
|
37
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(i).tgt_spec{1}(2).value = 'e';
|
38
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(i).sname = ['Realign: Estimate: Realigned Images (Sess' i ')'];
|
39
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(i).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
40
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(i).src_output = substruct('.','sess', '()',{i}, '.','cfiles');
|
41
|
+
end
|
42
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.template = {[spm('Dir') '/templates/EPI.nii,1']};
|
43
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.weight = '';
|
44
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.smosrc = 8;
|
45
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.smoref = 0;
|
46
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.regtype = 'mni';
|
47
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.cutoff = 25;
|
48
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.nits = 16;
|
49
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.reg = 1;
|
50
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.preserve = 0;
|
51
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.bb = [-78 -112 -50
|
52
|
+
78 76 85];
|
53
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.vox = [2 2 2];
|
54
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.interp = 1;
|
55
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.wrap = [0 0 0];
|
56
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.prefix = 'w';
|
57
|
+
matlabbatch{3}.spm.spatial.smooth.data(1) = cfg_dep;
|
58
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).tname = 'Images to Smooth';
|
59
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).tgt_spec{1}(1).name = 'filter';
|
60
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).tgt_spec{1}(1).value = 'image';
|
61
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).tgt_spec{1}(2).name = 'strtype';
|
62
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).tgt_spec{1}(2).value = 'e';
|
63
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).sname = 'Normalise: Estimate & Write: Normalised Images (Subj 1)';
|
64
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
65
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).src_output = substruct('()',{1}, '.','files');
|
66
|
+
matlabbatch{3}.spm.spatial.smooth.fwhm = [8 8 8];
|
67
|
+
matlabbatch{3}.spm.spatial.smooth.dtype = 0;
|
68
|
+
matlabbatch{3}.spm.spatial.smooth.im = 0;
|
69
|
+
matlabbatch{3}.spm.spatial.smooth.prefix = 's';
|
@@ -0,0 +1,76 @@
|
|
1
|
+
function [] = JohnsonTbiLongitudinalSnodStats(statsdir, images, image_boldreps, conditions, regressors, job_mfile)
|
2
|
+
|
3
|
+
% List of open inputs
|
4
|
+
% fMRI model specification: Directory - cfg_entry
|
5
|
+
% 6 Scans Each with:
|
6
|
+
% fMRI model specification: Scans
|
7
|
+
% fMRI model specification: Multiple Conditions File - cfg_entry
|
8
|
+
% fMRI model specification: Multiple Regressors File - cfg_entry
|
9
|
+
|
10
|
+
spm('defaults', 'FMRI');
|
11
|
+
|
12
|
+
% statsdir = '/private/tmp/mrt00015_stats/'
|
13
|
+
% images = { 'swamrt00015_task1.nii' 'swamrt00015_task2.nii' }
|
14
|
+
% image_boldreps = {164 164}
|
15
|
+
% regressors = { 'mrt00015_faces3_recognitionA.mat' 'mrt00015_faces3_recognitionB.mat' }
|
16
|
+
% job_mfile = '/private/tmp/mrt00015_stats/Merit220Stats_job.m'
|
17
|
+
|
18
|
+
nrun = 1; % enter the number of runs here
|
19
|
+
% jobfile = {'/private/tmp/mrt00015_proc/Merit220_Stats_job.m'};
|
20
|
+
jobfile = {job_mfile};
|
21
|
+
jobs = repmat(jobfile, 1, nrun);
|
22
|
+
inputs = cell(length(images) + 1, nrun);
|
23
|
+
|
24
|
+
% Load the first conditions file to get the length of the names.
|
25
|
+
eval(['load ' conditions{1}]);
|
26
|
+
|
27
|
+
switch numel(names)
|
28
|
+
case 2 % New, Old
|
29
|
+
fcontrast_vector = [1 0
|
30
|
+
0 1];
|
31
|
+
tcontrast_1_vector = [-1 1];
|
32
|
+
tcontrast_2_vector = [1 -1];
|
33
|
+
% case 4 % New_correct, New_incorrect, Old_correct, Old_incorrect
|
34
|
+
% fcontrast_vector = [1 0 0 0
|
35
|
+
% 0 1 0 0
|
36
|
+
% 0 0 1 0
|
37
|
+
% 0 0 0 1 ];
|
38
|
+
% tcontrast_1_vector = [-1 0 1 0];
|
39
|
+
% tcontrast_2_vector = [ 1 0 -1 0];
|
40
|
+
% case 5 % New_correct, New_incorrect, Old_correct, Old_incorrect, Misses
|
41
|
+
% fcontrast_vector = [1 0 0 0
|
42
|
+
% 0 1 0 0
|
43
|
+
% 0 0 1 0
|
44
|
+
% 0 0 0 1 ];
|
45
|
+
% tcontrast_1_vector = [-1 0 1 0];
|
46
|
+
% tcontrast_2_vector = [ 1 0 -1 0];
|
47
|
+
otherwise
|
48
|
+
error('Incorrect number of conditions detected: %d', numel(conditions));
|
49
|
+
end
|
50
|
+
|
51
|
+
for crun = 1:nrun
|
52
|
+
inputs{1, crun} = { statsdir }; % fMRI model specification: Directory - cfg_entry
|
53
|
+
|
54
|
+
% fMRI model specification: Directory - cfg_entry
|
55
|
+
for index = 1:length(images)
|
56
|
+
offset = (index - 1) .* 3;
|
57
|
+
inputs{offset + 2, crun} = CreateFunctionalVolumeStruct(statsdir, images{index}, image_boldreps{index}); % fMRI model specification: Scans - cfg_entry
|
58
|
+
inputs{offset + 3, crun} = { strcat(statsdir, conditions{index} ) }; % fMRI model specification: Multiple Conditions File - cfg_entry
|
59
|
+
inputs{offset + 4, crun} = { strcat(statsdir, regressors{index} ) }; % fMRI model specification: Multiple Regressors File - cfg_entry
|
60
|
+
end
|
61
|
+
|
62
|
+
image_offset = (length(images) .* 3) + 1;
|
63
|
+
inputs{image_offset + 1, crun} = 'Omnibus F'; % fMRI model specification: Omnibus Title - cfg_entry
|
64
|
+
inputs{image_offset + 2, crun} = fcontrast_vector; % fMRI model specification: Omnibus Contrast - cfg_entry
|
65
|
+
|
66
|
+
inputs{image_offset + 3, crun} = 'NV > PV'; % fMRI model specification: T Contrast 1 Title - cfg_entry
|
67
|
+
inputs{image_offset + 4, crun} = tcontrast_1_vector; % fMRI model specification: T Contrast 1 Vector - cfg_entry
|
68
|
+
|
69
|
+
inputs{image_offset + 5, crun} = 'PV > NV'; % fMRI model specification: T Contrast 2 Title - cfg_entry
|
70
|
+
inputs{image_offset + 6, crun} = tcontrast_2_vector; % fMRI model specification: T Contrast 2 Vector - cfg_entry
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
spm_jobman('serial', jobs, '', inputs{:});
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# require 'logfile'
|
2
|
+
module JohnsonTbiLongitudinalSnodStats
|
3
|
+
|
4
|
+
DEFAULT_CONDITIONS = [:new, :old]
|
5
|
+
|
6
|
+
# runs the complete set of tasks using data in a subject's "proc" directory and a preconfigured template spm job.
|
7
|
+
def run_first_level_stats
|
8
|
+
flash "Highway to the dangerzone..."
|
9
|
+
setup_directory(@statsdir, "STATS")
|
10
|
+
|
11
|
+
Dir.chdir(@statsdir) do
|
12
|
+
link_files_from_proc_directory(File.join(@procdir, "sw*.nii"), File.join(@procdir, "rp*.txt"))
|
13
|
+
setup_onsets
|
14
|
+
run_stats_spm_job
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method :perform, :run_first_level_stats
|
19
|
+
|
20
|
+
def setup_onsets
|
21
|
+
setup_conditions
|
22
|
+
create_or_link_onsets_files
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup_conditions
|
26
|
+
@conditions = @conditions ? @conditions.collect {|c| c.to_sym if c.respond_to? :to_sym } : DEFAULT_CONDITIONS
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_or_link_onsets_files
|
30
|
+
if @onsetsfiles.nil?
|
31
|
+
if @responses.nil?
|
32
|
+
raise ScriptError, "Condition vectors cannot be created because neither log response files nor onsets mat files have been specified."
|
33
|
+
else
|
34
|
+
@onsetsfiles = create_onsets_files(@responses, conditions)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
link_onsets_files
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Finally runs the stats job
|
42
|
+
def run_stats_spm_job
|
43
|
+
images = @scan_labels ? @scan_labels.collect! { |label| Dir.glob("sw*#{label}*.nii").to_s } : Dir.glob(File.join(@origdir, "sw*#{@subid}*.nii"))
|
44
|
+
raise ScriptError, "Can't find any smoothed, warped images in #{@statsdir}" if images.empty?
|
45
|
+
unless @onsetsfiles.length == @regressorsfiles.length && @regressorsfiles.length == @bold_reps.length
|
46
|
+
raise ScriptError, "Mismatch between #{@bold_reps.length} reps, #{@onsetsfiles.length} onsets and #{@regressorsfiles.length} regressors files."
|
47
|
+
end
|
48
|
+
|
49
|
+
queue = MatlabQueue.new
|
50
|
+
queue.paths << [
|
51
|
+
'/Applications/spm/spm8/spm8_current',
|
52
|
+
'/apps/spm/spm8_current',
|
53
|
+
File.join(@libdir, 'custom_methods'),
|
54
|
+
File.join(@libdir, 'matlab_helpers') ]
|
55
|
+
|
56
|
+
queue << "JohnsonTbiLongitudinalSnodStats('#{@statsdir}/', \
|
57
|
+
{ #{images.collect {|im| "'#{File.basename(im)}'"}.join(' ')} }, \
|
58
|
+
{ #{@bold_reps.join(' ') } }, \
|
59
|
+
{ #{@onsetsfiles.collect { |file| "'#{File.basename(file)}'"}.join(' ') } }, \
|
60
|
+
{ #{@regressorsfiles.collect { |file| "'#{File.basename(file)}'"}.join(' ') } }, \
|
61
|
+
'JohnsonTbiLongitudinalSnodStats_job.m')"
|
62
|
+
|
63
|
+
# puts queue.to_s
|
64
|
+
queue.run!
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
%-----------------------------------------------------------------------
|
2
|
+
% Job configuration created by cfg_util (rev $Rev: 3599 $)
|
3
|
+
%-----------------------------------------------------------------------
|
4
|
+
%% Specification
|
5
|
+
matlabbatch{1}.spm.stats.fmri_spec.dir = '<UNDEFINED>';
|
6
|
+
matlabbatch{1}.spm.stats.fmri_spec.timing.units = 'scans';
|
7
|
+
matlabbatch{1}.spm.stats.fmri_spec.timing.RT = 2;
|
8
|
+
matlabbatch{1}.spm.stats.fmri_spec.timing.fmri_t = 16;
|
9
|
+
matlabbatch{1}.spm.stats.fmri_spec.timing.fmri_t0 = 1;
|
10
|
+
for i = 1:2
|
11
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(i).scans = '<UNDEFINED>';
|
12
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(i).cond = struct('name', {}, 'onset', {}, 'duration', {}, 'tmod', {}, 'pmod', {});
|
13
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(i).multi = '<UNDEFINED>';
|
14
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(i).regress = struct('name', {}, 'val', {});
|
15
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(i).multi_reg = '<UNDEFINED>';
|
16
|
+
matlabbatch{1}.spm.stats.fmri_spec.sess(i).hpf = 128;
|
17
|
+
end
|
18
|
+
matlabbatch{1}.spm.stats.fmri_spec.fact = struct('name', {}, 'levels', {});
|
19
|
+
matlabbatch{1}.spm.stats.fmri_spec.bases.hrf.derivs = [0 0];
|
20
|
+
matlabbatch{1}.spm.stats.fmri_spec.volt = 1;
|
21
|
+
matlabbatch{1}.spm.stats.fmri_spec.global = 'None';
|
22
|
+
matlabbatch{1}.spm.stats.fmri_spec.mask = {''};
|
23
|
+
matlabbatch{1}.spm.stats.fmri_spec.cvi = 'AR(1)';
|
24
|
+
%% Estimation
|
25
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1) = cfg_dep;
|
26
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).tname = 'Select SPM.mat';
|
27
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).tgt_spec{1}(1).name = 'filter';
|
28
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).tgt_spec{1}(1).value = 'mat';
|
29
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).tgt_spec{1}(2).name = 'strtype';
|
30
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).tgt_spec{1}(2).value = 'e';
|
31
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).sname = 'fMRI model specification: SPM.mat File';
|
32
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
33
|
+
matlabbatch{2}.spm.stats.fmri_est.spmmat(1).src_output = substruct('.','spmmat');
|
34
|
+
matlabbatch{2}.spm.stats.fmri_est.method.Classical = 1;
|
35
|
+
%% Contrast Creation
|
36
|
+
matlabbatch{3}.spm.stats.con.spmmat(1) = cfg_dep;
|
37
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).tname = 'Select SPM.mat';
|
38
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).tgt_spec{1}(1).name = 'filter';
|
39
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).tgt_spec{1}(1).value = 'mat';
|
40
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).tgt_spec{1}(2).name = 'strtype';
|
41
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).tgt_spec{1}(2).value = 'e';
|
42
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).sname = 'Model estimation: SPM.mat File';
|
43
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
44
|
+
matlabbatch{3}.spm.stats.con.spmmat(1).src_output = substruct('.','spmmat');
|
45
|
+
matlabbatch{3}.spm.stats.con.consess{1}.fcon.name = '<UNDEFINED>';
|
46
|
+
matlabbatch{3}.spm.stats.con.consess{1}.fcon.convec{1} = '<UNDEFINED>';
|
47
|
+
matlabbatch{3}.spm.stats.con.consess{1}.fcon.sessrep = 'repl';
|
48
|
+
matlabbatch{3}.spm.stats.con.consess{2}.tcon.name = '<UNDEFINED>';
|
49
|
+
matlabbatch{3}.spm.stats.con.consess{2}.tcon.convec = '<UNDEFINED>';
|
50
|
+
matlabbatch{3}.spm.stats.con.consess{2}.tcon.sessrep = 'repl';
|
51
|
+
matlabbatch{3}.spm.stats.con.consess{3}.tcon.name = '<UNDEFINED>';
|
52
|
+
matlabbatch{3}.spm.stats.con.consess{3}.tcon.convec = '<UNDEFINED>';
|
53
|
+
matlabbatch{3}.spm.stats.con.consess{3}.tcon.sessrep = 'repl';
|
54
|
+
matlabbatch{3}.spm.stats.con.delete = 0;
|
55
|
+
|
56
|
+
% NOTE! F-contrasts expect cells containing contrast arrays, while
|
57
|
+
% T-contrasts expect the arrays themslves (hence the cell reference in
|
58
|
+
% F-contrast definition (convec{1} = [];) but not in T-contrast definition
|
59
|
+
% (convec = [];)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
# Setup Command and General Logs to point to STDOUT if not defined.
|
4
|
+
module DefaultLogger
|
5
|
+
def setup_logger
|
6
|
+
%w{$Log $CommandLog}.each do |log|
|
7
|
+
unless eval(log)
|
8
|
+
eval("#{log} = Log4r::Logger.new('output')")
|
9
|
+
eval("#{log}.add Log4r::StdoutOutputter.new(:stdout)")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module DefaultPreproc
|
2
|
+
|
3
|
+
# Runs the preprocessing job, including spm job customization, run spm job, and handling motion issues.
|
4
|
+
# This function assumes a destination directory is set up; it will overwrite preexisting data. Careful!
|
5
|
+
def preproc_visit
|
6
|
+
$Log.info "Spatial Preprocessing Subject: #{@subid}"
|
7
|
+
|
8
|
+
setup_directory(@procdir, "PREPROC")
|
9
|
+
|
10
|
+
Dir.chdir(@procdir) do
|
11
|
+
link_files_into_proc
|
12
|
+
customize_templates
|
13
|
+
run_spm_jobs
|
14
|
+
deal_with_motion
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method :perform, :preproc_visit
|
19
|
+
|
20
|
+
# Links all the slice timing corrected data from the source "orig" directory using a wildcard a${subid}*.nii,
|
21
|
+
# where subid is the subject id specified in the preproc_spec hash.
|
22
|
+
def link_files_into_proc
|
23
|
+
flash "Linking files from #{@origdir} into #{@procdir}"
|
24
|
+
wildcard = File.join(@origdir,"a*#{@subid}*.nii")
|
25
|
+
files = Dir.glob(wildcard)
|
26
|
+
unless files.empty?
|
27
|
+
system("ln -s #{wildcard} #{@procdir}")
|
28
|
+
else
|
29
|
+
raise(IOError, "No files matching #{wildcard} found.")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def check_permissions(files)
|
34
|
+
unwritable = []
|
35
|
+
files.collect { |file| unwritable << file unless File.writable?(file) }
|
36
|
+
raise IOError, "Cannot write to #{unwritable.join(", ")} files." unless unwritable.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Customizes the template job in preproc_spec to be specific for this particular preproc job.
|
40
|
+
# Performs to recursive string replacements inside the spm job:
|
41
|
+
# - path inside template is replaced with destination "proc" directory
|
42
|
+
# - subid inside template is replaced with the current subid
|
43
|
+
def customize_templates
|
44
|
+
flash "Customizing template SPM job: #{@tspec['job']}"
|
45
|
+
replacecmd = "spmjobStringReplace.sh"
|
46
|
+
|
47
|
+
templatejob = File.join(@spmdir, @tspec['job'])
|
48
|
+
thisjob = @subid + '_preproc.mat'
|
49
|
+
|
50
|
+
File.copy(templatejob, thisjob)
|
51
|
+
system("#{replacecmd} #{thisjob} #{@tspec['path']} #{@procdir} #{thisjob}")
|
52
|
+
system("#{replacecmd} #{thisjob} #{@tspec['subid']} #{@subid} #{thisjob}")
|
53
|
+
end
|
54
|
+
|
55
|
+
# Runs the customized spm job using the shell script runSpmJob.sh. Make sure this is available at your site.
|
56
|
+
def run_spm_jobs
|
57
|
+
thisjob = "#{@subid}_preproc.mat"
|
58
|
+
flash "Running spatial preprocessing SPM job: #{thisjob}"
|
59
|
+
system("runSpmJob.sh #{thisjob}")
|
60
|
+
end
|
61
|
+
|
62
|
+
# Calculates the realignment motion derivatives and checks that displacement
|
63
|
+
# in all directions was less than the MOTION_THRESHOLD. Operates on all files
|
64
|
+
# in the current working directory that match rp_a*txt (SPM convention). Uses
|
65
|
+
# two shell scripts that must both be available on the local machine:
|
66
|
+
# - calc_derivs.sh
|
67
|
+
# - fmri_motion_check.sh
|
68
|
+
def deal_with_motion
|
69
|
+
flash "Calculating motion derivatives and checking for excessive motion"
|
70
|
+
Dir.glob("rp_a*txt").each do |rp|
|
71
|
+
run("calc_derivs.sh #{rp}")
|
72
|
+
run("fmri_motion_check.sh #{rp} #{@motion_threshold}")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', '..', '..', 'physionoise/lib')
|
2
|
+
|
3
|
+
require 'metamri/core_additions'
|
4
|
+
require 'physionoise'
|
5
|
+
require 'pathname'
|
6
|
+
require 'default_methods/recon/physionoise_helper'
|
7
|
+
require 'default_methods/recon/raw_sequence'
|
8
|
+
|
9
|
+
module DefaultRecon
|
10
|
+
|
11
|
+
# Reconstructs, strips, and slice timing corrects all scans specified in the recon_spec.
|
12
|
+
# This function assumes a destination directory is set up in the filesystem and begins writing
|
13
|
+
# to it with no further checking. It will overwrite data if it already exists, be careful.
|
14
|
+
def recon_visit
|
15
|
+
|
16
|
+
setup_directory(@origdir, "RECON")
|
17
|
+
|
18
|
+
Dir.chdir(@origdir) do
|
19
|
+
@scans.each_with_index do |scan_spec, i|
|
20
|
+
outfile = "%s_%s.nii" % [@subid, scan_spec['label']]
|
21
|
+
|
22
|
+
reconstruct_scan(scan_spec, outfile)
|
23
|
+
|
24
|
+
if scan_spec['type'] == "func"
|
25
|
+
# if scan_spec['physio_files']
|
26
|
+
# create_physiosnoise_regressors(scan_spec)
|
27
|
+
# outfile = run_retroicor(scan_spec['physio_files'], outfile)
|
28
|
+
# end
|
29
|
+
|
30
|
+
slice_time_correct(outfile)
|
31
|
+
else
|
32
|
+
File.copy('tmp.nii', outfile)
|
33
|
+
end
|
34
|
+
|
35
|
+
File.delete('tmp.nii') if File.exist? 'tmp.nii'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :perform, :recon_visit
|
41
|
+
|
42
|
+
# Reconstructs a scan from dicoms or pfile to nifti, anatomical or functional.
|
43
|
+
# Uses a scan_spec hash to drive. Writes the result in current working
|
44
|
+
# directory. Raises an error if to3d system call fails. Conventions: I****.dcm
|
45
|
+
# filenaming, I0002.dcm is second file in series,
|
46
|
+
def reconstruct_scan(scan_spec, outfile)
|
47
|
+
if scan_spec['dir']
|
48
|
+
sequence = DicomRawSequence.new(scan_spec, @rawdir)
|
49
|
+
sequence.prepare('tmp.nii')
|
50
|
+
strip_leading_volumes('tmp.nii', outfile, @volume_skip, scan_spec['bold_reps'])
|
51
|
+
elsif scan_spec['pfile']
|
52
|
+
sequence = PfileRawSequence.new(scan_spec, @rawdir)
|
53
|
+
sequence.prepare(outfile)
|
54
|
+
else
|
55
|
+
raise ConfigError, "Scan must list either a pfile or a dicom directory."
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Removes the specified number of volumes from the beginning of a 4D functional nifti file.
|
60
|
+
# In most cases this will be 3 volumes. Writes result in current working directory.
|
61
|
+
def strip_leading_volumes(infile, outfile, volume_skip, bold_reps)
|
62
|
+
$Log.info "Stripping #{volume_skip.to_s} leading volumes: #{infile}"
|
63
|
+
cmd_fmt = "fslroi %s %s %s %s"
|
64
|
+
cmd_options = [infile, outfile, volume_skip.to_s, bold_reps.to_s]
|
65
|
+
cmd = cmd_fmt % cmd_options
|
66
|
+
unless run(cmd)
|
67
|
+
raise ScriptError, "Failed to strip volumes: #{cmd}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Uses to3d to slice time correct a 4D functional nifti file. Writes result in the current working directory.
|
72
|
+
def slice_time_correct(infile)
|
73
|
+
$Log.info "Slice Timing Correction: #{infile}"
|
74
|
+
cmd = "3dTshift -tzero 0 -tpattern alt+z -prefix a#{infile} #{infile}"
|
75
|
+
unless run(cmd)
|
76
|
+
raise ScriptError, "Failed to slice time correct: #{cmd}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|