rpipe 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/.document +5 -0
  2. data/.gitignore +23 -0
  3. data/LICENSE +20 -0
  4. data/README +0 -0
  5. data/README.rdoc +33 -0
  6. data/Rakefile +78 -0
  7. data/VERSION +1 -0
  8. data/bin/create_driver.rb +79 -0
  9. data/bin/rpipe +131 -0
  10. data/bin/swallow_batch_run.rb +21 -0
  11. data/lib/core_additions.rb +5 -0
  12. data/lib/custom_methods/JohnsonMerit220Visit1Preproc.m +26 -0
  13. data/lib/custom_methods/JohnsonMerit220Visit1Preproc.rb +43 -0
  14. data/lib/custom_methods/JohnsonMerit220Visit1Preproc_job.m +80 -0
  15. data/lib/custom_methods/JohnsonMerit220Visit1Stats.m +74 -0
  16. data/lib/custom_methods/JohnsonMerit220Visit1Stats.rb +63 -0
  17. data/lib/custom_methods/JohnsonMerit220Visit1Stats_job.m +63 -0
  18. data/lib/custom_methods/JohnsonTbiLongitudinalSnodPreproc.m +26 -0
  19. data/lib/custom_methods/JohnsonTbiLongitudinalSnodPreproc.rb +41 -0
  20. data/lib/custom_methods/JohnsonTbiLongitudinalSnodPreproc_job.m +69 -0
  21. data/lib/custom_methods/JohnsonTbiLongitudinalSnodStats.m +76 -0
  22. data/lib/custom_methods/JohnsonTbiLongitudinalSnodStats.rb +67 -0
  23. data/lib/custom_methods/JohnsonTbiLongitudinalSnodStats_job.m +59 -0
  24. data/lib/custom_methods/ReconWithHello.rb +7 -0
  25. data/lib/default_logger.rb +13 -0
  26. data/lib/default_methods/default_preproc.rb +76 -0
  27. data/lib/default_methods/default_recon.rb +80 -0
  28. data/lib/default_methods/default_stats.rb +94 -0
  29. data/lib/default_methods/recon/physionoise_helper.rb +69 -0
  30. data/lib/default_methods/recon/raw_sequence.rb +109 -0
  31. data/lib/generators/job_generator.rb +36 -0
  32. data/lib/generators/preproc_job_generator.rb +31 -0
  33. data/lib/generators/recon_job_generator.rb +76 -0
  34. data/lib/generators/stats_job_generator.rb +70 -0
  35. data/lib/generators/workflow_generator.rb +128 -0
  36. data/lib/global_additions.rb +18 -0
  37. data/lib/logfile.rb +310 -0
  38. data/lib/matlab_helpers/CreateFunctionalVolumeStruct.m +6 -0
  39. data/lib/matlab_helpers/import_csv.m +32 -0
  40. data/lib/matlab_helpers/matlab_queue.rb +37 -0
  41. data/lib/matlab_helpers/prepare_onsets_xls.m +30 -0
  42. data/lib/rpipe.rb +254 -0
  43. data/rpipe.gemspec +177 -0
  44. data/spec/generators/preproc_job_generator_spec.rb +27 -0
  45. data/spec/generators/recon_job_generator_spec.rb +33 -0
  46. data/spec/generators/stats_job_generator_spec.rb +50 -0
  47. data/spec/generators/workflow_generator_spec.rb +97 -0
  48. data/spec/helper_spec.rb +40 -0
  49. data/spec/integration/johnson.merit220.visit1_spec.rb +47 -0
  50. data/spec/integration/johnson.tbi.longitudinal.snod_spec.rb +48 -0
  51. data/spec/logfile_spec.rb +96 -0
  52. data/spec/matlab_queue_spec.rb +40 -0
  53. data/spec/merit220_stats_spec.rb +81 -0
  54. data/spec/physio_spec.rb +98 -0
  55. data/test/drivers/merit220_workflow_sample.yml +15 -0
  56. data/test/drivers/mrt00000.yml +65 -0
  57. data/test/drivers/mrt00015.yml +62 -0
  58. data/test/drivers/mrt00015_hello.yml +41 -0
  59. data/test/drivers/mrt00015_withphys.yml +81 -0
  60. data/test/drivers/tbi000.yml +129 -0
  61. data/test/drivers/tbi000_separatevisits.yml +137 -0
  62. data/test/drivers/tmp.yml +58 -0
  63. data/test/fixtures/faces3_recognitionA.mat +0 -0
  64. data/test/fixtures/faces3_recognitionA.txt +86 -0
  65. data/test/fixtures/faces3_recognitionA_equal.csv +25 -0
  66. data/test/fixtures/faces3_recognitionA_unequal.csv +21 -0
  67. data/test/fixtures/faces3_recognitionB_incmisses.txt +86 -0
  68. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CPd3R_40.txt +13360 -0
  69. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CPd3_40.txt +13360 -0
  70. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CPttl_40.txt +13360 -0
  71. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CRTd3R_40.txt +13360 -0
  72. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CRTd3_40.txt +13360 -0
  73. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_CRTttl_40.txt +13360 -0
  74. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_CRTd3R_40.txt +334 -0
  75. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_CRTd3_40.txt +334 -0
  76. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_CRTttl_40.txt +334 -0
  77. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_RRT_40.txt +334 -0
  78. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_RVT_40.txt +334 -0
  79. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_card_spline_40.txt +334 -0
  80. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_HalfTR_resp_spline_40.txt +334 -0
  81. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_RRT_40.txt +9106 -0
  82. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_RVT_40.txt +9106 -0
  83. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_CRTd3R_40.txt +167 -0
  84. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_CRTd3_40.txt +167 -0
  85. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_CRTttl_40.txt +167 -0
  86. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_RRT_40.txt +167 -0
  87. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_RVT_40.txt +167 -0
  88. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_card_spline_40.txt +167 -0
  89. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_TR_resp_spline_40.txt +167 -0
  90. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_card_spline_40.txt +13360 -0
  91. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_resp_spline_40.txt +9106 -0
  92. data/test/fixtures/physionoise_regressors/EPI__fMRI_Task1_resp_spline_downsampled_40.txt +9106 -0
  93. data/test/fixtures/ruport_summary.yml +123 -0
  94. data/test/fixtures/valid_scans.yaml +35 -0
  95. data/test/helper.rb +10 -0
  96. data/test/test_dynamic_method_inclusion.rb +10 -0
  97. data/test/test_includes.rb +11 -0
  98. data/test/test_integrative_johnson.merit220.visit1.rb +31 -0
  99. data/test/test_preproc.rb +11 -0
  100. data/test/test_recon.rb +11 -0
  101. data/test/test_rpipe.rb +19 -0
  102. data/vendor/output_catcher.rb +93 -0
  103. data/vendor/trollop.rb +781 -0
  104. metadata +260 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ ._*
6
+ *.tmproj
7
+ tmtags
8
+
9
+ ## EMACS
10
+ *~
11
+ \#*
12
+ .\#*
13
+
14
+ ## VIM
15
+ *.swp
16
+
17
+ ## PROJECT::GENERAL
18
+ coverage
19
+ rdoc
20
+ pkg
21
+
22
+ ## PROJECT::SPECIFIC
23
+ doc
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,5 @@
1
+ class String
2
+ def dot_camelize
3
+ self.gsub(/(?:^|\.|_)(.)/) { $1.upcase }
4
+ end
5
+ end
@@ -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{:});