generate_1st-lvl-design.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #!/usr/bin/python3
  2. '''
  3. created on Wed 19th 2020
  4. author: Christian Olaf Haeusler
  5. '''
  6. from glob import glob
  7. import argparse
  8. import os
  9. import re
  10. import subprocess
  11. SUBMIT_CONTENT = [
  12. '# auto-generate file (generate_1st_level_design.py) -- do not modify!',
  13. 'universe = vanilla',
  14. 'output = condor_logs/$(CLUSTER).$(PROCESS).out',
  15. 'error = condor_logs/$(CLUSTER).$(PROCESS).err',
  16. 'log = condor_logs/$(CLUSTER).$(PROCESS).log',
  17. 'getenv = True',
  18. 'request_cpus = 1',
  19. 'request_memory = 5000',
  20. 'should_transfer_files = NO',
  21. 'transfer_executable = False',
  22. 'initialdir = /data/project/studyforrest_ppa',
  23. 'executable = $ENV(FSLDIR)/bin/feat',
  24. '',
  25. ]
  26. def parse_arguments():
  27. '''
  28. '''
  29. parser = argparse.ArgumentParser(
  30. description='rename and copy the auditory \
  31. confound files to onset directories')
  32. parser.add_argument('-fmri',
  33. default='inputs/studyforrest-data-aligned/sub-01/in_bold3Tp2/sub-01_task-aomovie_run-1_bold.nii.gz',
  34. help='example 4d fmri file/path from sub-01')
  35. parser.add_argument('-design',
  36. default='code/1st-lvl_audio-ppa-grp.fsf',
  37. help='the design template (for sub-01)')
  38. args = parser.parse_args()
  39. fmriEx = args.fmri
  40. designFile = args.design
  41. return fmriEx, designFile
  42. # main program #
  43. if __name__ == "__main__":
  44. # prepare the header for the condor .submit file
  45. submit_content = [line + '\n' for line in SUBMIT_CONTENT]
  46. # with launch_ipdb_on_exception():
  47. # call FSL first
  48. os.system('. /etc/fsl/5.0/fsl.sh')
  49. fmri_example, design_file = parse_arguments()
  50. # for 3T data input
  51. if 'sub-01' in fmri_example:
  52. subjs_pattern = fmri_example.replace('sub-01', 'sub-*')
  53. # search for subjects
  54. pathes = sorted(glob(subjs_pattern))
  55. subjs = [re.search(r'sub-\d{2}', path) for path in pathes]
  56. subjs = [int(subj.group()[-2:]) for subj in subjs]
  57. # filter out sub-10 that is not in intersection of subjects for
  58. # both movie and audio-description (missing in audio-description)
  59. if 10 in subjs:
  60. subjs.remove(10)
  61. runs_pattern = fmri_example.replace('run-1', 'run-*')
  62. pathes = sorted(glob(runs_pattern))
  63. runs = [re.search(r'run-\d', path) for path in pathes]
  64. runs = [(run.group()) for run in runs]
  65. runs = [int(run[-1]) for run in runs]
  66. else:
  67. print('subject string not found')
  68. # open design file
  69. with open(design_file, 'r') as f:
  70. lines = f.readlines()
  71. # use the design file as template
  72. template = [line.strip() for line in lines]
  73. for sub in subjs:
  74. sub = str(sub)
  75. print('\nsub', sub)
  76. for run in runs:
  77. run = str(run)
  78. print('run', run)
  79. # number of fmri volumes for current run
  80. fmri_file = fmri_example.replace('sub-01', 'sub-' + sub.zfill(2))
  81. fmri_file = fmri_file.replace('run-1', 'run-' + run)
  82. info = subprocess.check_output('fslinfo %s' % fmri_file, shell=True)
  83. dim4 = info.split()[9]
  84. vol = str(dim4).split("'")[1]
  85. design_file_content = []
  86. for lineNo, line in enumerate(template):
  87. if 'sub-01' in line or 'run-1' in line:
  88. line = line.replace('sub-01', 'sub-' + sub.zfill(2))
  89. line = line.replace('run-1', 'run-' + run)
  90. # correct bold_dico_moco.txt (motion correction for audio data)
  91. elif 'sub001' in line or 'run001' in line:
  92. line = line.replace('sub001', 'sub' + sub.zfill(3))
  93. line = line.replace('run001', 'run' + run.zfill(3))
  94. elif 'set fmri(npts) ' in line:
  95. line_splitted = line.split()
  96. line_splitted[-1] = ' ' + vol
  97. line = ' '.join(line_splitted)
  98. elif 'set fmri(evtitle' in line:
  99. # check for the corresponding EV3 file
  100. # it's name comes always 31 lines later in the file
  101. ev = line.split('"')[1]
  102. ev_file_line = template[lineNo + 31]
  103. ev_file = ev_file_line.split('"')[1]
  104. ev_file = ev_file.replace('sub-01', 'sub-' + sub.zfill(2))
  105. ev_file = ev_file.replace('run-1', 'run-' + run)
  106. if os.path.isfile(ev_file):
  107. with open(ev_file, 'r') as f:
  108. content = f.readlines()
  109. length = len(content)
  110. # check the length of the event onset file
  111. # use canonical HRF if it contains lines/events
  112. if length > 0:
  113. fmri_shape = '3'
  114. # use 0 regressor otherwise
  115. else:
  116. fmri_shape = '10'
  117. print('no events in', ev_file)
  118. print('choosing null events for ev %s' % ev)
  119. else:
  120. print('could not find', ev_file)
  121. fmri_shape = '10'
  122. print('choosing null events for ev %s' % ev)
  123. elif 'set fmri(shape' in line:
  124. line_splitted = line.split()
  125. line_splitted[-1] = fmri_shape
  126. line = ' '.join(line_splitted)
  127. design_file_content.append(line)
  128. design_file_content = [line + '\n' for line in design_file_content]
  129. # writing
  130. fsl_design = os.path.basename(design_file).split('.')[0]
  131. analysis = fsl_design.split('lvl_')[1]
  132. out_name = 'run-%s_1st_%s.fsf' % (run, analysis)
  133. out_path = os.path.join('sub-' + sub.zfill(2), out_name)
  134. try:
  135. with open(out_path, 'w') as the_file:
  136. the_file.writelines(design_file_content)
  137. submit_arg = 'arguments = sub-%s/%s\nqueue\n' % (sub.zfill(2), out_name)
  138. submit_content.append(submit_arg)
  139. except IOError:
  140. print(sub, 'is not in intersection of movie and audio-description')
  141. # write the condor_submit file
  142. submit_name = 'compute_1st-lvl_%s.submit' % analysis
  143. submit_path = os.path.join(os.path.dirname(design_file), submit_name)
  144. with open(submit_path, 'w') as the_file:
  145. the_file.writelines(submit_content)
  146. os.makedirs('condor_logs', exist_ok=True)