#!/usr/bin/env python import sys, string, glob, os import afni_base, afni_util # the main interface for updating SubjProcStream options via questions def ask_me_subj_proc(proc): # start by displaying overview print """ ----------------------------------------------------------------------- *** The -ask_me method is no longer well supported. Consider *** *** following the examples from the -help output. Or better yet, *** *** try uber_subject.py, the graphical interface to afni_proc.py. *** ----------------------------------------------------------------------- This ask_me dialogue is designed to give users a feel for the basic options they may want to supply when not using -ask_me. It reviews only a subset of possible options. (see "afni_proc.py -help" for the full list :). This program minimally requires a list of AFNI datasets to process, and a list of stimulus files, if regression is to be run. Unless options were previously specified, options for each of these processing blocks will be requested: setup, tcat, tshift, volreg, blur, mask, scale, regress At the end, there will be a chance to store the complete afni_proc.py command in a text file for future use. ----------------------------------------------------------------------- """ # start by looking for datasets if len(proc.dsets) == 0: if get_datasets(proc): return 1 print '---------- setup block --------------------------------------\n' if not proc.user_opts.find_opt('-subj_id'): print "----- requesting '-subj_id' option\n" print " The subject identifier is used in the processing director\n"\ " name, as well as names of datasets which are created.\n" word = read_one_word('++ please enter a subject ID: ') print " (applying '-subj_id %s')\n" % word proc.user_opts.add_opt('-subj_id', 1, [word],setpar=1) if not proc.user_opts.find_opt('-script'): print "----- requesting '-script' option\n" print " This is the name of the output processing script.\n" word = read_one_word('++ please enter a script name: ') print " (applying '-script %s')\n" % word proc.user_opts.add_opt('-script', 1, [word],setpar=1) print '---------- tcat block --------------------------------------\n' if not proc.user_opts.find_opt('-tcat_remove_first_trs'): print "----- requesting '-tcat_remove_first_trs' option\n" print " This option is used to remove the EPI volumes that\n" \ " were acquired before the scanner reached a steady\n" \ " state. The default number to remove is 0.\n\n" \ " Note: it is essential that the stimulus timing files\n" \ " match the removal of these TRs.\n" val = read_one_int('++ please enter the number of TRs to remove: ') print " (applying '-tcat_remove_first_trs %d')\n" % val proc.user_opts.add_opt('-tcat_remove_first_trs', 1, [str(val)], setpar=1) print '---------- tshift block --------------------------------------\n' print " Slices will be temporally aligned with the start of each TR.\n" print " (applying '-tshift_align_to -tzero 0')\n" print '---------- volreg block --------------------------------------\n' if not proc.user_opts.find_opt('-volreg_align_to'): print "----- requesting '-volreg_align_to' option\n" print " All EPI volumes will be aligned to the volume that was\n" \ " acquired closest to when the anatomical volume was\n" \ " acquired. Valid inputs are 'first' and 'last', meaning\n" \ " the first volume of the first run, or the last volume of\n" \ " the last run.\n" word = read_one_word("++ align to 'first' or 'last' volume: ", ['first', 'last']) print " (applying '-volreg_align_to %s')\n" % word proc.user_opts.add_opt('-volreg_align_to', 1, [word],setpar=1) print '---------- mask block --------------------------------------\n' print " '3dAutomask -dilate 1' will be used to create a mask for" print " each run. From those, a union mask will be created.\n" print " (applying default '-mask_dilate 1' and '-mask_type union')\n" print '---------- scale block --------------------------------------\n' print " Each EPI run will be scaled to a mean of 100. Values above\n" print " 200 will be truncated to 200.\n" print " (applying default '-scale_max_val 200')\n" print '---------- regress block --------------------------------------\n' if not proc.user_opts.find_opt('-regress_basis'): print "---------- requesting '-regress_basis' option\n" print " The basis function will be convolved with the stimulus\n" \ " onset times within 3dDeconvolve (the same function will be\n" \ " applied to each stimulus class).\n" \ " Examples: GAM - the default\n" \ " BLOCK(5,1) - for 5 second stimuli\n" \ " BLOCK(20,1) - for 20 second stimuli\n" \ " TENT(0,14,8) - deconvolution, with an expected\n" \ " reponse lasting 14 seconds after\n" \ " each stimulus, with beta weights\n" \ " locked to a 2 second TR grid over\n"\ " 7 intervals (so 8 tents)\n" word = read_one_word('++ please enter a basis function: ') print " (applying -regress_basis '%s')\n" % word proc.user_opts.add_opt('-regress_basis', 1, [word],setpar=1) # get stim_times or stim_files if not proc.user_opts.find_opt('-regress_stim_times') and \ not proc.user_opts.find_opt('-regress_stim_files'): if get_stim_files(proc, word): return 1 if not proc.user_opts.find_opt('-regress_stim_labels'): if get_stim_labels(proc,type): return 1 # apply the new options (and old ones, again) if proc.apply_initial_opts(proc.user_opts): return 1 def get_stim_labels(proc, type): print "---------- requesting stimulus labels\n" print "Stimulus labels should match the order of the -stim_times or\n" \ " -stim_files parameters.\n" nlabs = read_one_int('++ enter the number of stimulus labels: ', pos=1) if proc.verb > 1: print 'want %d stim labels\n' % nlabs while 1: # break when done print 'Please enter the list of stim labels.\n' nremain = nlabs labels = [] while nremain > 0 : print '++ (%d remain) please enter label(s): ' % nremain, llist = string.split(sys.stdin.readline()) if not llist or len(llist) <= 0: continue labels += llist nremain -= len(llist) if nremain < 0: print '\n** error: too many labels were given (%d > %d)\n' \ ' please start again...\n' % (nlabs-nremain, nlabs) continue break print " (applying: -regress_stim_labels %s)\n" % (' '.join(labels)) proc.user_opts.add_opt('-regress_stim_labels', -1, labels, setpar=1) def get_stim_files(proc, type): print "---------- requesting stimuli...\n" print "Stimuli can be given as one of\n" \ " 'times' : stim_times files, with times in seconds\n" \ " 'files' : 0/1 stim_files, listing which TRs had stimuli\n" type = read_one_word("++ apply stim 'files' or 'times': ", ['files','times']) nfiles = read_one_int('++ enter the number of files for stim_%s: '%type, pos=1) if proc.verb > 1: print 'want %d stim_%s\n' % (nfiles,type) while 1: # break when done print 'Please enter stim names, wildcard use is okay.\n' \ '(wildcards okay only if order of names is alphabetical)\n' nremain = nfiles files = [] while nremain > 0 : print '++ (%d remain) please enter file name(s): ' % nremain, flist = read_one_glob_file_list() if not flist or len(flist) <= 0: continue # we could test for valid stim_files/times here files += flist nremain -= len(flist) if nremain < 0: print '\n** error: too many names were given (%d > %d)\n' \ ' please start again...\n' % (nfiles-nremain, nfiles) continue break print " (applying: -regress_stim_%s %s)\n" % (type, ' '.join(files)) proc.user_opts.add_opt('-regress_stim_%s'%type, -1, files, setpar=1) def get_datasets(proc): print '-- Datasets are required (no -dsets option was given).\n' \ ' Enter the names in the order that should will be processed.\n' ndsets = read_one_int('++ enter the number of datasets: ',pos=1) if proc.verb > 1: print 'ndsets = %d\n' % ndsets while 1: # break when done print 'Please enter dataset names, wildcard use is okay.\n' \ '(wildcards okay only if order of names is alphabetical)\n' nremain = ndsets dsets = [] errs = 0 while nremain > 0 and errs == 0: print '++ (%d remain) please enter dataset name(s): ' % nremain, words = string.split(sys.stdin.readline()) print # for separation new_dsets = afni_util.list_to_datasets(words, whine=1) if new_dsets and len(new_dsets) == 0: continue if not new_dsets: continue # good idea? # if we god a new dataset list, append it and check for repeats dsets += new_dsets if not afni_util.uniq_list_as_dsets(dsets, 1): errs += 1 else: nremain -= len(new_dsets) if proc.verb > 1: print '+d have %d valid dset name(s): %s'%(len(words),words) # 2 checks for continuation: errors or too many datasets if errs: print '\nsorry, there were errors, please start over...\n' continue if nremain < 0: print '\n** error: too many names were given (%d > %d)\n' \ ' please start again...\n' % (ndsets-nremain, ndsets) continue break # if we get here, things look good if proc.verb > 0: print '-- have %d valid datasets (-dsets)\n'%(len(dsets)) proc.dsets = dsets # read a list of file names from the command line # exand any wildcards # check each for existence # return None on error def read_one_glob_file_list(): words = string.split(sys.stdin.readline()) print # for separation # walk through list, instead of using map(), allows error checking wlist = [] for word in words: # each is either a word or a glob expression glist = glob.glob(word) if glist: glist.sort() wlist += glist else: wlist.append(word) flist = [] errs = 0 for file in wlist: # now check for existence if os.path.isfile(file): flist.append(file) else: print "** no file match for '%s'" % file errs = 1 if errs: return None return flist # read a single word from a command line, and return it # - a list of valid possibilities may be passed # - try until success def read_one_word(prompt, valid_list=None): while 1: print prompt, words = string.split(sys.stdin.readline()) print # for separation if len(words) <= 0: continue if not valid_list or words[0] in valid_list: break return words[0] # read a single integer from a command line, and return it # - try until success # - pos -> integer must be positive def read_one_int(prompt, pos=0, nonneg=0): while 1: print prompt, words = string.split(sys.stdin.readline()) print # for separation if len(words) < 1: continue if words[0] in ['quit', 'QUIT', 'exit', 'EXIT']: print 'exiting on user request...\n' sys.exit(0) try: val = int(words[0]) except: continue if pos and val <= 0: continue if nonneg and val < 0: continue return val # if we're here, all is well