Skip to content

Commit

Permalink
Add Qbi runner refactor tool, and resulting config files & schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
martinherrerias committed Oct 12, 2023
1 parent 57006ba commit cd9d9c9
Show file tree
Hide file tree
Showing 16 changed files with 409 additions and 0 deletions.
1 change: 1 addition & 0 deletions config/DCE_ETM.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
madym_config_file: null
1 change: 1 addition & 0 deletions config/DCE_VFA_T1_mapping.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
madym_config_file: null
27 changes: 27 additions & 0 deletions config/DCE_deltaCt.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

# General (previously Qbi.runner options)
#data_dir: null
output_dir: logs/qMRI_processes
# no_audit: True # -- this is a madym option

# Inputs
dce_path: dce/dce_dyn_echo1
T1_path: madym_output/T1_VFA/T1.nii.gz

dce_im_ext: .nii.gz
dce_meta_ext: .json
#roi_path: null

# Parameters
dce_limits: [2, 9, 11, 15]
relax_coeff: 0
average_fun: median
alternative: less
equal_var: True

# Output
maps_dir: DCE_output_maps




Empty file.
4 changes: 4 additions & 0 deletions config/OE_DCE_summary.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
summary_dir: 'summary_outputs'
final_maps_dir: 'masked_maps'
roi_masks_dir: 'roi_masks'
suffixes: ['sig_5pct', 'sig_5pct_bf', 'sig_forman']
1 change: 1 addition & 0 deletions config/OE_IR_T1_mapping.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
madym_config_file: null
12 changes: 12 additions & 0 deletions config/OE_deltaR1.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
roi_path: null
oe_path: 'oxygen/oe'
oe_im_ext: '.nii.gz'
oe_meta_ext: '.json'
oe_limits: null
T1_path: 'madym_output/T1_IR/T1.nii.gz'
efficiency_path: 'madym_output/T1_IR/efficiency.nii.gz'
average_fun: 'median'
alternative: 'less'
equal_var: True
sig_level: 0.05
maps_dir: 'OE_output_maps'
110 changes: 110 additions & 0 deletions dev/refactor_qbi_runner_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
'''
Take a python script.py with Qbi.runner.parser calls of the form:
parser.add('--param', type=str, default='foo', nargs=?, required=True,
help='description')
parser.add('--param2', type=int, default=42, nargs=3, help='description 2')
Write a YAML config file script.config.yaml
param: 'foo'
param2: 42
And a JSON-schema file script.schema.yaml
param:
type: string
default: 'foo'
description: 'description'
#required: True
param2:
type: integer
default: 42
description: 'description 2'
#nargs: 3
'''
import re
import sys

def replace_blocks(input_file, output_file, patterns, block_pattern = r'[\s\S]*'):

with open(input_file, 'r') as file:
content = file.read()

if isinstance(block_pattern, str):
block_pattern = (block_pattern,)

matches = re.finditer(block_pattern[0], content, re.MULTILINE | re.DOTALL)

content = ''
if matches:
for match in matches:

matched_text = match.group()

# Optional block substitution
if len(block_pattern) == 2:
matched_text = re.sub(block_pattern[0], block_pattern[1], matched_text)

# print(f'\n{matched_text}\n')

# Replace internal patterns
for old_pattern, new_pattern in patterns:
matched_text = re.sub(old_pattern, new_pattern, matched_text)

# print(f'old: {old_pattern}, new: {new_pattern}')
# print(f'\n{matched_text}\n')

# Replace the matched text in the original content
content = content + matched_text + '\n'

# print(content)

with open(output_file, 'w') as file:
file.write(content)

print(f'Replacements in {input_file} completed successfully.')
else:
print('No matches found for the specified block pattern.')

if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python refactor_qbi_runner_parser.py <input_file>")
sys.exit(1)

input_file_path = sys.argv[1]

output_schema = re.sub(r'\.py$', r'.schema.yaml', input_file_path)
output_config = re.sub(r'\.py$', r'.config.yaml', input_file_path)

# Matches complete parser.add(...) call, keeps arguments only
block_pattern = (r'^\s*parser.add\(([\s\S]*?)\)$', r'\g<1>')

# Write configuration file with list: param: default
config_patterns = [
(r"\n\s+", r' '), # remove line breaks
(r"^'?--(\w*).*default=(\[[^]]*\]|'[^']*'|[^,)]*).*", r'\g<1>: \g<2>'), # --param, ..., default=foo
(r"^'?--(\w*).*", r'\g<1>: None')
]
replace_blocks(input_file_path, output_config, config_patterns, block_pattern)

# Write schema with type, description, etc.
schema_patterns = [
(r"\n\s+", r' '), # remove line breaks
(r"^'?--(\w*)'?", r'\g<1>:'), # --param
(r",\s*type=([^,)]*)", r'\n type: \g<1>'), # type=foo
(r",\s*default=(\[[^]]*\]|'[^']*'|[^,)]*)", r'\n default: \g<1>'), # default=bar
(r",\s*help=('[^']*'|[^,)]*)", r'\n description: \g<1>'), # help='...'
(r",\s*nargs='\?'", r''), # dump args='?'
(r",\s*(\w*)=('[^']*'|[^,)]*)", r'\n #\g<1>: \g<2>'), # comment everything else
]
replace_blocks(input_file_path, output_schema, schema_patterns, block_pattern)

#
type_patterns = [
(r" type: '?str'?", r' type: string'),
(r" type: '?int'?", r' type: integer'),
(r" type: '?float'?", r' type: number'),
(r" type: '?bool_option'?", r' type: boolean')
]
replace_blocks(output_schema, output_schema, type_patterns)
10 changes: 10 additions & 0 deletions workflow/schemas/DCE_ETM.schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
$schema: "https://json-schema.org/draft/2020-12/schema"

description: foo

properties:
madym_config_file:
type: string, required = False
description: ''


10 changes: 10 additions & 0 deletions workflow/schemas/DCE_VFA_T1_mapping.schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
$schema: "https://json-schema.org/draft/2020-12/schema"

description: foo

properties:
madym_config_file:
type: string, required = False
description: ''


82 changes: 82 additions & 0 deletions workflow/schemas/DCE_deltaCt.schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
$schema: "https://json-schema.org/draft/2020-12/schema"

description: an entry in the sample sheet

properties:
#General input arguments
data_dir:
type: string
description: 'Base data path'
default: './test'

roi_path:
type: ["null", string]
description: 'Relative path to roi mask file'
default: null

#Output dir
maps_dir:
type: string
description: 'Location of saved output maps, relative to data_dir'
default: 'DCE_output_maps'

#DCE input options
dce_path:
type: string
description: 'Relative path to DCE 4D-image volumes'
default: 'dynamic'

dce_im_ext:
type: string
description: 'File extension of the DCE volumes'
default: '.nii.gz'

dce_meta_ext:
type: string
description: 'File extension of the DCE volumes meta-info'
default: '.json'

dce_limits:
type: array
items:
type: integer
maxItems: 4
minItems: 4
description: 'Limits for the DCE volumes, 4 element integer list specifiying the timepoints for [baseline_start, baseline_, oxygen_start, oxygen_]'

T1_path:
type: string
description: 'Relative path to T1 image'
default: 'madym_output/T1_VFA/T1.nii.gz'

relax_coeff:
type: number
description: 'Relaxivity constant for contrast agent - units... '
default: 3.4

#Summary stats options
average_fun:
type: string
enum:
- median
- mean
description: 'Method used for temporal average {median, mean}.'
default: median

alternative:
type: string
enum:
- less
- two-sided
- greater
description: 'Apply 1-sided or 2-sided t-test: "less" = baseline lower than enhancing. Use "two-sided" for 2-sided.'
default: less

equal_var:
type: boolean
default: true
description: 'Assume equal variance in pre/post enhancing periods'

required:
- data_dir
- dce_limits
1 change: 1 addition & 0 deletions workflow/schemas/OE_DCE_hypoxia_mapping.schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

24 changes: 24 additions & 0 deletions workflow/schemas/OE_DCE_summary.schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
$schema: "https://json-schema.org/draft/2020-12/schema"

description: foo

properties:
summary_dir:
type: string
default: 'summary_outputs'
description: ''
final_maps_dir:
type: string
default: 'masked_maps'
description: ''
roi_masks_dir:
type: string
default: 'roi_masks'
description: ''
suffixes:
type: string
#nargs: 3
default: ['sig_5pct', 'sig_5pct_bf', 'sig_forman']
description: ''


5 changes: 5 additions & 0 deletions workflow/schemas/OE_IR_T1_mapping.schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
madym_config_file:
type: string, required = False
description: ''


56 changes: 56 additions & 0 deletions workflow/schemas/OE_deltaR1.schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
$schema: "https://json-schema.org/draft/2020-12/schema"

description: foo

properties:
roi_path:
type: string
default: null
description: 'Relative path to roi mask file'
oe_path:
type: string
default: 'oxygen/oe'
description: 'Relative path to OE 4D-image volumes'
oe_im_ext:
type: string
default: '.nii.gz'
description: 'File extension of the OE volumes'
oe_meta_ext:
type: string
default: '.json'
description: 'File extension of the OE volumes meta-info'
oe_limits:
type: integer
#nargs: 4
#required: True
description: 'Limits for the OE volumes, 4 element integer list'
T1_path:
type: string
default: 'madym_output/T1_IR/T1.nii.gz'
description: 'Relative path to T1 image'
efficiency_path:
type: string
default: 'madym_output/T1_IR/efficiency.nii.gz'
description: 'Relative path to T1 efficiency image'
average_fun:
type: string
default: 'median'
description: 'Method used for temporal average {median, mean}.'
alternative:
type: string
default: 'less'
description: 'Apply 1-sided or 2-sided t-test: less = baseline lower than enhancing. Use "equal" for 2-sided.'
equal_var:
type: boolean
default: True, const = True
description: 'Assume equal variance in pre/post enhancing periods'
sig_level:
type: number
default: 0.05
description: 'Significance level for p-value map thresholds'
maps_dir:
type: string
default: 'OE_output_maps'
description: 'Location of saved output maps, relative to data_dir'


Loading

0 comments on commit cd9d9c9

Please sign in to comment.