Class: WorkflowGenerator

Inherits:
JobGenerator show all
Defined in:
lib/generators/workflow_generator.rb

Overview

A class for parsing a data directory and creating default Driver Configurations Intialize a WorkflowGenerator with a Raw Directory containing Scans and with the following optional keys in a config hash:

Directory Options:

- processing_dir : A directory common to  orig, proc and stats directories, if they are not explicitly specified..
- origdir : A directory where dicoms will be converted to niftis and basic preprocessing occurs.
- procdir : A directory for detailed preprocessing (normalization and smoothing)
- statsdir : A directory where stats will be saved.  (This should be a final directory.)

Instance Attribute Summary collapse

Attributes inherited from JobGenerator

#previous_step

Instance Method Summary collapse

Methods inherited from JobGenerator

#config_requires, #spec_validates

Constructor Details

#initialize(rawdir, config = Hash.new) ⇒ WorkflowGenerator

Returns a new instance of WorkflowGenerator.



23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/generators/workflow_generator.rb', line 23

def initialize(rawdir, config = Hash.new)
  config_defaults = {}
  config_defaults['conditions'] = ['new_correct', 'new_incorrect', 'old_correct', 'old_incorrect']
  config_defaults['processing_dir'] = Dir.mktmpdir
  super config_defaults.merge(config)
  
  @rawdir = rawdir
  @spec['rawdir'] = @rawdir
  @spec['subid'] = parse_subid
  @spec['study_procedure'] = @config['study_procedure'] ||= guess_study_procedure_from(@rawdir)

  # config_requires 'responses_dir'
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



21
22
23
# File 'lib/generators/workflow_generator.rb', line 21

def config
  @config
end

#specObject (readonly)

Returns the value of attribute spec.



21
22
23
# File 'lib/generators/workflow_generator.rb', line 21

def spec
  @spec
end

Instance Method Details

#buildObject

Create and return a workflow spec to drive processing



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/generators/workflow_generator.rb', line 38

def build    
  configure_directories
  
  @spec['collision'] = 'destroy'
  
  
  jobs = []
  
  # Recon
  recon_options = {'rawdir' => @rawdir, 'epi_pattern' => /(Rest|Task)/i, }
  config_step_method(recon_options, 'recon') if @config['custom_methods']
  jobs << ReconJobGenerator.new(recon_options).build
  
  # Preproc
  preproc_options = {'scans' => jobs.first['scans']}
  config_step_method(preproc_options, 'preproc') if @config['custom_methods']
  jobs << PreprocJobGenerator.new(preproc_options).build
  
  # Stats
  stats_options = {
    'scans' => jobs.first['scans'],
    'conditions' => @config['conditions'],
    'responses_dir' => @config['responses_dir'],
    'subid' => @spec['subid']
  }
  config_step_method(stats_options, 'stats') if @config['custom_methods']
  jobs << StatsJobGenerator.new(stats_options).build
  
  @spec['jobs'] = jobs
  
  return @spec
end

#config_step_method(options, step) ⇒ Object

Configure Custom Methods from the Workflow Driver

Custom methods may be simply set to true for a given job or listed explicitly. If true, they will set the method to the a camelcased version of the study_procedure and step, i.e. JohnsonMerit220Visit1Stats If listed explicitly, it will set the step to the value listed.



126
127
128
129
130
131
132
# File 'lib/generators/workflow_generator.rb', line 126

def config_step_method(options, step)
  if @config['custom_methods'][step].class == String
    options['method'] = @config['custom_methods'][step]
  elsif @config['custom_methods'][step] == true
    options['method'] = [@config['study_procedure'], step.capitalize].join("_").dot_camelize
  end
end

#configure_directoriesObject

Handle Directory Configuration and Defaults for orig, proc and stats dirs.



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/generators/workflow_generator.rb', line 82

def configure_directories
  processing_dir = @config['processing_dir']
  if @config['directory_formats']
    @spec['origdir']  = @config['origdir']  || parse_directory_format(@config['directory_formats']['origdir'])  || File.join(processing_dir, @spec['subid'] + '_orig')
    @spec['procdir']  = @config['procdir']  || parse_directory_format(@config['directory_formats']['procdir'])  || File.join(processing_dir, @spec['subid'] + '_proc')
    @spec['statsdir'] = @config['statsdir'] || parse_directory_format(@config['directory_formats']['statsdir']) || File.join(processing_dir, @spec['subid'] + '_stats')
  else
    @spec['origdir']  = @config['origdir']  || File.join(processing_dir, @spec['subid'] + '_orig')
    @spec['procdir']  = @config['procdir']  || File.join(processing_dir, @spec['subid'] + '_proc')
    @spec['statsdir'] = @config['statsdir'] || File.join(processing_dir, @spec['subid'] + '_stats')
  end
end

#guess_study_procedure_from(dir) ⇒ Object

Guess a StudyProcedure from the data’s raw directory. A properly formed study procdure should be: <PI>.<Study>.<Description or Visit> Raises a ScriptError if it couldn’t guess a reasonable procedure.

Raises:

  • (ScriptError)


111
112
113
114
115
116
117
118
# File 'lib/generators/workflow_generator.rb', line 111

def guess_study_procedure_from(dir)
  dirs = dir.split("/")
  while dirs.empty? == false do
    current_dir = dirs.pop
    return current_dir if current_dir =~ /\w*\.\w*\.\w*/
  end
  raise ScriptError, "Could not guess study procedure from #{dir}"
end

#parse_directory_format(fmt) ⇒ Object

Replace a directory format string with respective values from the spec. For example, replace the string “/Data/<study_procedure>/<subid>/stats” from a workflow_driver[‘statsdir’] with “/Data/johnson.merit220.visit1/mrt00000/stats”



99
100
101
102
103
104
105
106
# File 'lib/generators/workflow_generator.rb', line 99

def parse_directory_format(fmt)
  dir = fmt.dup
  dir.scan(/<\w*>/).each do |replacement|
    key = replacement.to_s.gsub(/(<|>)/, '')
    dir.sub!(/<\w*>/, @spec[key])
  end
  return dir
end

#parse_subidObject

Guesses a Subject Id from @rawdir Takes the split basename of rawdir itself if rawdir includes subdir, or the basename of its parent.



74
75
76
77
78
79
# File 'lib/generators/workflow_generator.rb', line 74

def parse_subid
  subject_path = File.basename(@rawdir) == 'dicoms' ? 
    Pathname.new(File.join(@rawdir, '..')).realpath : Pathname.new(@rawdir).realpath
  
  subject_path.basename.to_s.split('_').first
end