rpipe 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Kristopher Kosmatka
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
File without changes
|
data/README.rdoc
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
= rpipe
|
2
|
+
|
3
|
+
RPipe parses and processes MRI data through nifti file conversion (or reconstruction for Pfiles, not currently supported), preprocessing and basic first-level statistics using SPM.
|
4
|
+
|
5
|
+
== Note on Usage
|
6
|
+
|
7
|
+
Use consists of parsing a directory using job and workflow generators to create a Yaml driver file, and then running that driver through RPipe.
|
8
|
+
|
9
|
+
Since not all studies are processed the same way, custom methods can be included in the main processing stream and can override as many methods as necessary to customize the workflow. Include a 'method' key in the step you wish to customize in the yaml driver file and then put customizations into lib/custom_methods.
|
10
|
+
|
11
|
+
Preprocessing and Stats use SPM, which is notoriously painful to use programatically (it's designed mainly as a GUI program). SPM8 included an easy to way to "harvest" job information, and we have included several Matlab helpers to for default Normalization and Stats jobs. See the _job.m files in custom methods for more detail.
|
12
|
+
|
13
|
+
== Dependencies
|
14
|
+
|
15
|
+
Raw MRI information is read from DICOM headers using the metamri parser gem, which in turn depends on RubyDicom (in the future) and dicom_hdr (AFNI).
|
16
|
+
|
17
|
+
Button-press response Logfile parsing is done using the Ruport reporting gem as a frontend store. This is probably more complicated than it needed to be, but should be robust in the future.
|
18
|
+
|
19
|
+
All three primary neuroimaging packages, SPM, AFNI, and FSL are required for various steps in the default pipeline.
|
20
|
+
- Reconstruction depends on to3d (AFNI), discdacq removal on fslroi (FSL), slicetiming on 3dTshift (AFNI).
|
21
|
+
- Preprocessing depends on SPM
|
22
|
+
- Stats depends on SPM
|
23
|
+
|
24
|
+
- http://www.fil.ion.ucl.ac.uk/spm/
|
25
|
+
- http://afni.nimh.nih.gov/afni
|
26
|
+
- http://www.fmrib.ox.ac.uk/fsl
|
27
|
+
|
28
|
+
== History
|
29
|
+
|
30
|
+
RPipe replaces the WADRC-fMRI-Pipeline, a pipeline previously used for preprocessing that was ported into python from bash. That thing was a beast!
|
31
|
+
|
32
|
+
== Copyright
|
33
|
+
Copyright (c) 2010 WADRC Neuroimaging Core. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "rpipe"
|
8
|
+
gem.summary = %Q{Neuroimaging preprocessing the Ruby way}
|
9
|
+
gem.description = %Q{Neuroimaging preprocessing the Ruby way}
|
10
|
+
gem.email = "kjkosmatka@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/brainmap/rpipe"
|
12
|
+
gem.authors = ["Kristopher Kosmatka", "Erik Kastman"]
|
13
|
+
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
14
|
+
gem.add_dependency "metamri"
|
15
|
+
gem.add_dependency "log4r"
|
16
|
+
gem.add_dependency "POpen4"
|
17
|
+
gem.add_dependency "ruport"
|
18
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rake/testtask'
|
26
|
+
Rake::TestTask.new(:test) do |test|
|
27
|
+
test.libs << 'lib' << 'test'
|
28
|
+
test.pattern = 'test/**/test_*.rb'
|
29
|
+
test.verbose = true
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
require 'rcov/rcovtask'
|
34
|
+
Rcov::RcovTask.new do |test|
|
35
|
+
test.libs << 'test'
|
36
|
+
test.pattern = 'test/**/test_*.rb'
|
37
|
+
test.verbose = true
|
38
|
+
end
|
39
|
+
rescue LoadError
|
40
|
+
task :rcov do
|
41
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
begin
|
46
|
+
require 'spec/rake/spectask'
|
47
|
+
Spec::Rake::SpecTask.new do |test|
|
48
|
+
test.warning = true
|
49
|
+
# test.rcov = true
|
50
|
+
test.spec_files = FileList['spec/**/*_spec.rb']
|
51
|
+
end
|
52
|
+
rescue LoadError
|
53
|
+
task :spec do
|
54
|
+
abort "RSpec is not available. In order to run specs, you must: sudo gem install rspec"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
task :test => :check_dependencies
|
60
|
+
|
61
|
+
task :default => [:spec, :test]
|
62
|
+
|
63
|
+
begin
|
64
|
+
gem 'darkfish-rdoc'
|
65
|
+
require 'darkfish-rdoc/rdoctask'
|
66
|
+
rescue LoadError
|
67
|
+
"Not using darkfish."
|
68
|
+
end
|
69
|
+
require 'rake/rdoctask'
|
70
|
+
Rake::RDocTask.new do |rdoc|
|
71
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
72
|
+
|
73
|
+
rdoc.rdoc_dir = 'rdoc'
|
74
|
+
rdoc.title = "rpipe #{version}"
|
75
|
+
rdoc.rdoc_files.include('README*')
|
76
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
77
|
+
rdoc.options += ['darkfish']
|
78
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'rubygems'
|
4
|
+
require 'optparse'
|
5
|
+
require 'pp'
|
6
|
+
require 'generators/workflow_generator'
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
def create!
|
11
|
+
# Parse CLI Options and Spec File
|
12
|
+
cli_options = parse_options
|
13
|
+
spec_options = cli_options[:spec_file] ? load_spec(cli_options[:spec_file]) : {}
|
14
|
+
|
15
|
+
workflow_options_defaults = {}
|
16
|
+
workflow_options = workflow_options_defaults.merge(spec_options).merge(cli_options[:config])
|
17
|
+
|
18
|
+
# Create a Workflow Generator and use it to create configure job.
|
19
|
+
rawdir = ARGV.pop
|
20
|
+
workflow = WorkflowGenerator.new(rawdir, workflow_options)
|
21
|
+
if cli_options[:dry_run]
|
22
|
+
pp workflow.build
|
23
|
+
else
|
24
|
+
write_file(workflow.build)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
def write_file(workflow_spec, filename = nil)
|
31
|
+
filename ||= workflow_spec['subid'] + '.yaml'
|
32
|
+
|
33
|
+
File.open(filename, 'w') { |f| f.puts workflow_spec.to_yaml }
|
34
|
+
raise IOError, "Couldn't write #{filename}}" unless File.exist?(filename)
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_spec(spec_file)
|
38
|
+
if File.exist?(spec_file)
|
39
|
+
spec = YAML::load_file(spec_file)
|
40
|
+
else
|
41
|
+
raise IOError, "Cannot find yaml spec file #{spec_file}"
|
42
|
+
end
|
43
|
+
|
44
|
+
return spec
|
45
|
+
end
|
46
|
+
|
47
|
+
def parse_options
|
48
|
+
options = { :config => {} }
|
49
|
+
parser = OptionParser.new do |opts|
|
50
|
+
opts.banner = "Usage: #{File.basename(__FILE__)} [options] RAWDIR"
|
51
|
+
|
52
|
+
opts.on('-s', '--spec SPEC', "Spec File for common study parameters") do |spec_file|
|
53
|
+
options[:spec_file] = spec_file
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on('-r', '--responses_dir RESPONSES_DIR', "Directory containing Button-press Response Logfiles") do |responses_dir|
|
57
|
+
options[:config][:responses_dir.to_s] = responses_dir
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.on('-d', '--dry-run', "Display Driver without executing it.") do
|
61
|
+
options[:dry_run] = true
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.on_tail('-h', '--help', "Show this message") { puts(parser); exit }
|
65
|
+
opts.on_tail("Example: #{File.basename(__FILE__)} mrt00001")
|
66
|
+
end
|
67
|
+
parser.parse!(ARGV)
|
68
|
+
|
69
|
+
if ARGV.size == 0
|
70
|
+
puts "Problem with arguments - Missing RAWDIR"
|
71
|
+
puts(parser); exit
|
72
|
+
end
|
73
|
+
|
74
|
+
return options
|
75
|
+
end
|
76
|
+
|
77
|
+
if __FILE__ == $0
|
78
|
+
create!
|
79
|
+
end
|
data/bin/rpipe
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'vendor')
|
4
|
+
begin
|
5
|
+
require 'trollop'
|
6
|
+
require 'output_catcher'
|
7
|
+
require 'pp'
|
8
|
+
require 'log4r'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rubygems'
|
11
|
+
retry
|
12
|
+
end
|
13
|
+
require 'rpipe'
|
14
|
+
|
15
|
+
STEPS = %w(recon preproc stats)
|
16
|
+
VERSION_NUMBER = "0.0.0"
|
17
|
+
VERSION_LINE = "rpipe %s WADRC Imaging Core" % VERSION_NUMBER
|
18
|
+
BANNER = <<-EOS
|
19
|
+
A utility for running neuroimaging rpipe jobs.
|
20
|
+
|
21
|
+
Usage: rpipe [options] <driver>
|
22
|
+
EOS
|
23
|
+
|
24
|
+
# Main Function for the CLI runner.
|
25
|
+
def run!
|
26
|
+
options, driver = setup_options
|
27
|
+
run_with_logging File.basename(driver, File.extname(driver)) do
|
28
|
+
$Log.info "Begin Pipelining #{driver}"
|
29
|
+
run_pipe(options, driver)
|
30
|
+
$Log.info "Finished Pipelining #{driver}"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
# Perform Each of the Jobs in a Pipe
|
36
|
+
def run_pipe(options, driver)
|
37
|
+
|
38
|
+
pipe = RPipe.new(driver)
|
39
|
+
pp pipe if options[:debug]
|
40
|
+
|
41
|
+
if options[:only_given]
|
42
|
+
case options[:only]
|
43
|
+
when "recon"
|
44
|
+
pipe.recon_jobs.each { |job| job.perform }
|
45
|
+
when "preproc"
|
46
|
+
pipe.preproc_jobs.each { |job| job.perform }
|
47
|
+
when "stats"
|
48
|
+
pipe.stats_jobs.each { |job| job.perform }
|
49
|
+
end
|
50
|
+
else
|
51
|
+
pipe.recon_jobs.each { |job| job.perform }
|
52
|
+
pipe.preproc_jobs.each { |job| job.perform }
|
53
|
+
pipe.stats_jobs.each { |job| job.perform }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Setup Trollop Options
|
58
|
+
def setup_options
|
59
|
+
opts = Trollop::options do
|
60
|
+
version VERSION_LINE
|
61
|
+
banner BANNER
|
62
|
+
opt :only, "Perform only a certain step (recon, preproc, stats)", :type => String
|
63
|
+
opt :debug, "Be more wordy than usual for debugging"
|
64
|
+
end
|
65
|
+
|
66
|
+
if opts[:only_given]
|
67
|
+
unless STEPS.include?(opts[:only])
|
68
|
+
Trollop::die :only, "must be one of recon, preproc, or stats"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
Trollop::die "Driver file not given" if (ARGV.size < 1)
|
73
|
+
driver = ARGV.shift
|
74
|
+
Trollop::die :driver, "file does not exist" unless File.exist?(driver)
|
75
|
+
|
76
|
+
pp opts if opts[:debug]
|
77
|
+
|
78
|
+
return opts, driver
|
79
|
+
end
|
80
|
+
|
81
|
+
# Setup Tee IO's for Out and Error and start logs for them.
|
82
|
+
def run_with_logging(logfile_stem, &block)
|
83
|
+
out_logfile = logfile_stem + '.out'
|
84
|
+
error_logfile = logfile_stem + '.err'
|
85
|
+
command_logfile = logfile_stem + '.log'
|
86
|
+
|
87
|
+
teeout = Tee.new(out_logfile, :out)
|
88
|
+
teeerr = Tee.new(error_logfile, :err)
|
89
|
+
|
90
|
+
setup_logger(command_logfile, teeout)
|
91
|
+
|
92
|
+
begin
|
93
|
+
yield
|
94
|
+
ensure
|
95
|
+
# Discard the error log if there were no errors.
|
96
|
+
# Size returns nil for an empty file.
|
97
|
+
teeerr.close
|
98
|
+
File.delete(error_logfile) unless File.size?(error_logfile)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Log Commands to a file and Output to stdout
|
103
|
+
def setup_logger(command_logfile, tee)
|
104
|
+
console_pattern = "#{'*' * 10} %m [ %d ]"
|
105
|
+
$Log = Log4r::Logger.new('output')
|
106
|
+
$Log.add Log4r::IOOutputter.new(:stdout, tee, :formatter => FlashFormatter.new)
|
107
|
+
|
108
|
+
File.delete command_logfile if File.exist? command_logfile
|
109
|
+
$CommandLog = Log4r::Logger.new('command::output')
|
110
|
+
$CommandLog.add Log4r::FileOutputter.new(:file, :filename => command_logfile, :formatter => Log4r::PatternFormatter.new(:pattern => "%m"))
|
111
|
+
$CommandLog.add Log4r::IOOutputter.new(:stdout, tee, :formatter => FlashFormatter.new)
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
# Formatter for Logging
|
116
|
+
class FlashFormatter < Log4r::Formatter
|
117
|
+
# Easy-to-read formatting
|
118
|
+
def format(logevent)
|
119
|
+
buff = "\n"
|
120
|
+
buff << "+" * 120 + "\n"
|
121
|
+
buff << sprintf("\t%s\n", logevent.data)
|
122
|
+
buff << sprintf("\t%s\n", Time.now)
|
123
|
+
buff << "+" * 120 + "\n"
|
124
|
+
buff << "\n"
|
125
|
+
return buff
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
if __FILE__ == $0
|
130
|
+
run!
|
131
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'rpipe'
|
4
|
+
|
5
|
+
yml_driver = ARGV[0]
|
6
|
+
|
7
|
+
p = RPipe.new(yml_driver)
|
8
|
+
|
9
|
+
exit
|
10
|
+
|
11
|
+
p.recon_jobs.each do |reconjob|
|
12
|
+
reconjob.setup_destination_directory
|
13
|
+
reconjob.recon_visit
|
14
|
+
end
|
15
|
+
|
16
|
+
p.preproc_jobs[0].setup_proc_dir
|
17
|
+
p.preproc_jobs[0..2].each do |pj|
|
18
|
+
pj.link_files_into_proc
|
19
|
+
end
|
20
|
+
p.preproc_jobs[0].preproc_visit
|
21
|
+
p.preproc_jobs[3].preproc_visit
|
@@ -0,0 +1,26 @@
|
|
1
|
+
function [] = JohnsonMerit220Visit1Preproc(studypath, images, image_boldreps, job_mfile)
|
2
|
+
% [] = merit_preproc Calls and runs Merit220 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
|
+
% List of open inputs
|
10
|
+
% Realign: Estimate: Session - cfg_files
|
11
|
+
% Realign: Estimate: Session - cfg_files
|
12
|
+
% Realign: Estimate: Session - cfg_files
|
13
|
+
|
14
|
+
spm('defaults', 'FMRI');
|
15
|
+
|
16
|
+
nrun = 1; % enter the number of runs here
|
17
|
+
jobfile = {job_mfile};
|
18
|
+
jobs = repmat(jobfile, 1, nrun);
|
19
|
+
inputs = cell(3, nrun);
|
20
|
+
|
21
|
+
for crun = 1:nrun
|
22
|
+
for index = 1:length(images)
|
23
|
+
inputs{index, crun} = CreateFunctionalVolumeStruct(studypath, images{index}, image_boldreps{index}); % Realign: Estimate: Session - cfg_files
|
24
|
+
end
|
25
|
+
end
|
26
|
+
spm_jobman('serial', jobs, '', inputs{:});
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'matlab_helpers/matlab_queue'
|
2
|
+
module JohnsonMerit220Visit1Preproc
|
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
|
+
check_permissions(image_files)
|
13
|
+
run_preproc_mfile
|
14
|
+
deal_with_motion
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method :perform, :preproc_visit
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def image_files
|
23
|
+
@image_files ||= Dir.glob(File.join(@origdir, "a*#{@subid}*.nii"))
|
24
|
+
end
|
25
|
+
|
26
|
+
def run_preproc_mfile
|
27
|
+
raise ScriptError, "Can't find any slice-time corrected images in #{@origdir}" if image_files.empty?
|
28
|
+
queue = MatlabQueue.new
|
29
|
+
queue.paths << ['/Applications/spm/spm8/spm8_current',
|
30
|
+
'/apps/spm/spm8_current',
|
31
|
+
File.join(@libdir, 'custom_methods'),
|
32
|
+
File.join(@libdir, 'matlab_helpers')
|
33
|
+
]
|
34
|
+
|
35
|
+
queue << "JohnsonMerit220Visit1Preproc('#{@procdir}/', \
|
36
|
+
{ #{image_files.collect {|im| "'#{File.basename(im)}'"}.join(' ')} }, \
|
37
|
+
{ #{@bold_reps.join(' ') } }, \
|
38
|
+
'JohnsonMerit220Visit1Preproc_job.m')"
|
39
|
+
|
40
|
+
queue.run!
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
%-----------------------------------------------------------------------
|
2
|
+
% Job configuration created by cfg_util (rev $Rev: 3599 $)
|
3
|
+
%-----------------------------------------------------------------------
|
4
|
+
matlabbatch{1}.spm.spatial.realign.estimate.data = {
|
5
|
+
'<UNDEFINED>'
|
6
|
+
'<UNDEFINED>'
|
7
|
+
'<UNDEFINED>'
|
8
|
+
}';
|
9
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.quality = 0.9;
|
10
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.sep = 4;
|
11
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.fwhm = 5;
|
12
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.rtm = 1;
|
13
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.interp = 2;
|
14
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.wrap = [0 0 0];
|
15
|
+
matlabbatch{1}.spm.spatial.realign.estimate.eoptions.weight = {''};
|
16
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1) = cfg_dep;
|
17
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).tname = 'Source Image';
|
18
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).tgt_spec{1}(1).name = 'filter';
|
19
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).tgt_spec{1}(1).value = 'image';
|
20
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).tgt_spec{1}(2).name = 'strtype';
|
21
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).tgt_spec{1}(2).value = 'e';
|
22
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).sname = 'Realign: Estimate: Realigned Images (Sess 1)';
|
23
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
24
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.source(1).src_output = substruct('.','sess', '()',{1}, '.','cfiles');
|
25
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.wtsrc = '';
|
26
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(1) = cfg_dep;
|
27
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(1).tname = 'Images to Write';
|
28
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(1).tgt_spec{1}(1).name = 'filter';
|
29
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(1).tgt_spec{1}(1).value = 'image';
|
30
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(1).tgt_spec{1}(2).name = 'strtype';
|
31
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(1).tgt_spec{1}(2).value = 'e';
|
32
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(1).sname = 'Realign: Estimate: Realigned Images (Sess 1)';
|
33
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
34
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(1).src_output = substruct('.','sess', '()',{1}, '.','cfiles');
|
35
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(2) = cfg_dep;
|
36
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(2).tname = 'Images to Write';
|
37
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(2).tgt_spec{1}(1).name = 'filter';
|
38
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(2).tgt_spec{1}(1).value = 'image';
|
39
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(2).tgt_spec{1}(2).name = 'strtype';
|
40
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(2).tgt_spec{1}(2).value = 'e';
|
41
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(2).sname = 'Realign: Estimate: Realigned Images (Sess 2)';
|
42
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(2).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
43
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(2).src_output = substruct('.','sess', '()',{2}, '.','cfiles');
|
44
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(3) = cfg_dep;
|
45
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(3).tname = 'Images to Write';
|
46
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(3).tgt_spec{1}(1).name = 'filter';
|
47
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(3).tgt_spec{1}(1).value = 'image';
|
48
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(3).tgt_spec{1}(2).name = 'strtype';
|
49
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(3).tgt_spec{1}(2).value = 'e';
|
50
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(3).sname = 'Realign: Estimate: Realigned Images (Sess 3)';
|
51
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(3).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
52
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.subj.resample(3).src_output = substruct('.','sess', '()',{3}, '.','cfiles');
|
53
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.template = {[spm('dir') '/templates/EPI.nii,1']};
|
54
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.weight = '';
|
55
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.smosrc = 8;
|
56
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.smoref = 0;
|
57
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.regtype = 'mni';
|
58
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.cutoff = 25;
|
59
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.nits = 16;
|
60
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.eoptions.reg = 1;
|
61
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.preserve = 0;
|
62
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.bb = [-78 -112 -50
|
63
|
+
78 76 85];
|
64
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.vox = [2 2 2];
|
65
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.interp = 1;
|
66
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.wrap = [0 0 0];
|
67
|
+
matlabbatch{2}.spm.spatial.normalise.estwrite.roptions.prefix = 'w';
|
68
|
+
matlabbatch{3}.spm.spatial.smooth.data(1) = cfg_dep;
|
69
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).tname = 'Images to Smooth';
|
70
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).tgt_spec{1}(1).name = 'filter';
|
71
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).tgt_spec{1}(1).value = 'image';
|
72
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).tgt_spec{1}(2).name = 'strtype';
|
73
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).tgt_spec{1}(2).value = 'e';
|
74
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).sname = 'Normalise: Estimate & Write: Normalised Images (Subj 1)';
|
75
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
|
76
|
+
matlabbatch{3}.spm.spatial.smooth.data(1).src_output = substruct('()',{1}, '.','files');
|
77
|
+
matlabbatch{3}.spm.spatial.smooth.fwhm = [8 8 8];
|
78
|
+
matlabbatch{3}.spm.spatial.smooth.dtype = 0;
|
79
|
+
matlabbatch{3}.spm.spatial.smooth.im = 0;
|
80
|
+
matlabbatch{3}.spm.spatial.smooth.prefix = 's';
|
@@ -0,0 +1,74 @@
|
|
1
|
+
function [] = Merit220Stats(statsdir, images, image_boldreps, conditions, regressors, job_mfile)
|
2
|
+
|
3
|
+
% List of open inputs
|
4
|
+
% fMRI model specification: Directory - cfg_entry
|
5
|
+
% fMRI model specification: Scans
|
6
|
+
% fMRI model specification: Multiple Conditions File - cfg_entry
|
7
|
+
% fMRI model specification: Multiple Regressors File - cfg_entry
|
8
|
+
% fMRI model specification: Scans
|
9
|
+
% fMRI model specification: Multiple Conditions File - cfg_entry
|
10
|
+
% fMRI model specification: Multiple Regressors File - cfg_entry
|
11
|
+
|
12
|
+
spm('defaults', 'FMRI');
|
13
|
+
|
14
|
+
% statsdir = '/private/tmp/mrt00015_stats/'
|
15
|
+
% images = { 'swamrt00015_task1.nii' 'swamrt00015_task2.nii' }
|
16
|
+
% image_boldreps = {164 164}
|
17
|
+
% regressors = { 'mrt00015_faces3_recognitionA.mat' 'mrt00015_faces3_recognitionB.mat' }
|
18
|
+
% job_mfile = '/private/tmp/mrt00015_stats/Merit220Stats_job.m'
|
19
|
+
|
20
|
+
nrun = 1; % enter the number of runs here
|
21
|
+
% jobfile = {'/private/tmp/mrt00015_proc/Merit220_Stats_job.m'};
|
22
|
+
jobfile = {job_mfile};
|
23
|
+
jobs = repmat(jobfile, 1, nrun);
|
24
|
+
inputs = cell(5, nrun);
|
25
|
+
|
26
|
+
% Load the first conditions file to get the length of the names.
|
27
|
+
eval(['load ' conditions{1}]);
|
28
|
+
|
29
|
+
switch numel(names)
|
30
|
+
case 2 % New, Old
|
31
|
+
fcontrast_vector = [1 0
|
32
|
+
0 1 ];
|
33
|
+
tcontrast_1_vector = [-1 1];
|
34
|
+
tcontrast_2_vector = [1 -1];
|
35
|
+
case 4 % New_correct, New_incorrect, Old_correct, Old_incorrect
|
36
|
+
fcontrast_vector = [1 0 0 0
|
37
|
+
0 1 0 0
|
38
|
+
0 0 1 0
|
39
|
+
0 0 0 1 ];
|
40
|
+
tcontrast_1_vector = [-1 0 1 0];
|
41
|
+
tcontrast_2_vector = [ 1 0 -1 0];
|
42
|
+
case 5 % New_correct, New_incorrect, Old_correct, Old_incorrect, Misses
|
43
|
+
fcontrast_vector = [1 0 0 0
|
44
|
+
0 1 0 0
|
45
|
+
0 0 1 0
|
46
|
+
0 0 0 1 ];
|
47
|
+
tcontrast_1_vector = [-1 0 1 0];
|
48
|
+
tcontrast_2_vector = [ 1 0 -1 0];
|
49
|
+
otherwise
|
50
|
+
error('Incorrect number of conditions detected: %d', numel(conditions));
|
51
|
+
end
|
52
|
+
|
53
|
+
for crun = 1:nrun
|
54
|
+
inputs{1, crun} = { statsdir }; % fMRI model specification: Directory - cfg_entry
|
55
|
+
|
56
|
+
% fMRI model specification: Directory - cfg_entry
|
57
|
+
for index = 1:length(images)
|
58
|
+
offset = (index - 1) .* 3;
|
59
|
+
inputs{offset + 2, crun} = CreateFunctionalVolumeStruct(statsdir, images{index}, image_boldreps{index}); % fMRI model specification: Scans - cfg_entry
|
60
|
+
inputs{offset + 3, crun} = { strcat(statsdir, conditions{index} ) }; % fMRI model specification: Multiple Conditions File - cfg_entry
|
61
|
+
inputs{offset + 4, crun} = { strcat(statsdir, regressors{index} ) }; % fMRI model specification: Multiple Regressors File - cfg_entry
|
62
|
+
inputs{offset + 5, crun} = 'Omnibus F'; % fMRI model specification: Omnibus Title - cfg_entry
|
63
|
+
inputs{offset + 6, crun} = fcontrast_vector; % fMRI model specification: Omnibus Contrast - cfg_entry
|
64
|
+
inputs{offset + 7, crun} = 'PV > NV'; % fMRI model specification: T Contrast 1 Title - cfg_entry
|
65
|
+
inputs{offset + 8, crun} = tcontrast_1_vector; % fMRI model specification: T Contrast 1 Vector - cfg_entry
|
66
|
+
inputs{offset + 9, crun} = 'NV > PV'; % fMRI model specification: T Contrast 2 Title - cfg_entry
|
67
|
+
inputs{offset + 10, crun} = tcontrast_2_vector; % fMRI model specification: T Contrast 2 Vector - cfg_entry
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
spm_jobman('serial', jobs, '', inputs{:});
|