def recon_all(subj_id,anatomies): '''Run the ``recon_all`` script''' if not environ_setup: setup_freesurfer() if isinstance(anatomies,basestring): anatomies = [anatomies] nl.run([os.path.join(freesurfer_home,'bin','recon-all'),'-all','-subjid',subj_id] + [['-i',anat] for anat in anatomies])
def atlas_overlap(dset, atlas=None): '''aligns ``dset`` to the TT_N27 atlas and returns ``(cost,overlap)``''' atlas = find_atlas(atlas) if atlas == None: return None cost_func = 'crM' infile = os.path.abspath(dset) tmpdir = tempfile.mkdtemp() with nl.run_in(tmpdir): o = nl.run([ '3dAllineate', '-verb', '-base', atlas, '-source', infile + '[0]', '-NN', '-final', 'NN', '-cost', cost_func, '-nmatch', '20%', '-onepass', '-fineblur', '2', '-cmass', '-prefix', 'test.nii.gz' ]) m = re.search(r'Final\s+cost = ([\d.]+) ;', o.output) if m: cost = float(m.group(1)) o = nl.run(['3dmaskave', '-mask', atlas, '-q', 'test.nii.gz'], stderr=None) data_thresh = float(o.output) / 4 i = nl.dset_info('test.nii.gz') o = nl.run([ '3dmaskave', '-q', '-mask', 'SELF', '-sum', nl.calc([atlas, 'test.nii.gz'], 'equals(step(a-10),step(b-%.2f))' % data_thresh) ], stderr=None) overlap = 100 * float( o.output) / (i.voxel_dims[0] * i.voxel_dims[1] * i.voxel_dims[2]) try: shutil.rmtree(tmpdir) except: pass return (cost, overlap)
def main (): start_time = datetime.datetime.now() print('Tiempo inicial', start_time) #Iniciar Spark sc = init_spark() spark = SparkSession(sc) # Conexion a sqlite c = init_sqlite() # Generar una lista con todos los generos y asignarle un numero a cada uno genres = load_genres(c) # Cargar la data a un dataframe data, headers_feature = load_dataset(c, spark, genres) # Correr la clasificacion por regresion logistica regression.run(data, headers_feature) # Correr la clasificacion por redes neuronales neural.run(data, headers_feature) end_time = datetime.datetime.now() print('Tiempo final', end_time) print('Tiempo total transcurrido', end_time - start_time)
def skullstrip_template(dset, template, prefix=None, suffix=None, dilate=0): '''Takes the raw anatomy ``dset``, aligns it to a template brain, and applies a templated skullstrip. Should produce fairly reliable skullstrips as long as there is a decent amount of normal brain and the overall shape of the brain is normal-ish''' if suffix == None: suffix = '_sstemplate' if prefix == None: prefix = nl.suffix(dset, suffix) if not os.path.exists(prefix): with nl.notify('Running template-based skull-strip on %s' % dset): dset = os.path.abspath(dset) template = os.path.abspath(template) tmp_dir = tempfile.mkdtemp() cwd = os.getcwd() with nl.run_in(tmp_dir): nl.affine_align(template, dset, skull_strip=None, cost='mi', opts=['-nmatch', '100%']) nl.run([ '3dQwarp', '-minpatch', '20', '-penfac', '10', '-noweight', '-source', nl.suffix(template, '_aff'), '-base', dset, '-prefix', nl.suffix(template, '_qwarp') ], products=nl.suffix(template, '_qwarp')) info = nl.dset_info(nl.suffix(template, '_qwarp')) max_value = info.subbricks[0]['max'] nl.calc([dset, nl.suffix(template, '_qwarp')], 'a*step(b-%f*0.05)' % max_value, prefix) shutil.move(prefix, cwd) shutil.rmtree(tmp_dir)
def roi_stats(mask,dset): out_dict = {} values = [{'Med': 'median', 'Min': 'min', 'Max': 'max', 'NZMean': 'nzmean', 'NZSum': 'nzsum', 'NZSigma': 'nzsigma', 'Mean': 'mean', 'Sigma': 'sigma', 'Mod': 'mode','NZcount':'nzvoxels'}, {'NZMod': 'nzmode', 'NZMed': 'nzmedian', 'NZMax': 'nzmax', 'NZMin': 'nzmin','Mean':'mean'}] options = [['-nzmean','-nzsum','-nzvoxels','-minmax','-sigma','-nzsigma','-median','-mode'], ['-nzminmax','-nzmedian','-nzmode']] if not nl.dset_grids_equal((mask,dset)): i = nl.dset_info(dset) grid_hash = '_' + '_'.join([str(x) for x in (i.voxel_size + i.voxel_dims)]) new_mask = nl.suffix(mask,grid_hash) if not os.path.exists(new_mask): nl.run(["3dfractionize","-template",dset,"-input",nl.calc(mask,"a",datum="short"),"-prefix",new_mask,"-preserve","-clip","0.2"]) mask = new_mask for i in xrange(len(values)): cmd = ['3dROIstats','-1Dformat','-nobriklab','-mask',mask] + options[i] + [dset] out = subprocess.check_output(cmd).split('\n') header = [(values[i][x.split('_')[0]],int(x.split('_')[1])) for x in out[1].split()[1:]] for j in xrange(len(out)/2-1): stats = [float(x) for x in out[(j+1)*2+1][1:].split()] for s in xrange(len(stats)): roi = header[s][1] stat_name = header[s][0] stat = stats[s] if roi not in out_dict: out_dict[roi] = {} out_dict[roi][stat_name] = stat return out_dict
def align_epi_anat(anatomy, epi_dsets, skull_strip_anat=True): ''' aligns epis to anatomy using ``align_epi_anat.py`` script :epi_dsets: can be either a string or list of strings of the epi child datasets :skull_strip_anat: if ``True``, ``anatomy`` will be skull-stripped using the default method The default output suffix is "_al" ''' if isinstance(epi_dsets, basestring): epi_dsets = [epi_dsets] if len(epi_dsets) == 0: nl.notify('Warning: no epi alignment datasets given for anatomy %s!' % anatomy, level=nl.level.warning) return if all(os.path.exists(nl.suffix(x, '_al')) for x in epi_dsets): return anatomy_use = anatomy if skull_strip_anat: nl.skull_strip(anatomy, '_ns') anatomy_use = nl.suffix(anatomy, '_ns') inputs = [anatomy_use] + epi_dsets dset_products = lambda dset: [ nl.suffix(dset, '_al'), nl.prefix(dset) + '_al_mat.aff12.1D', nl.prefix(dset) + '_tsh_vr_motion.1D' ] products = nl.flatten([dset_products(dset) for dset in epi_dsets]) with nl.run_in_tmp(inputs, products): if nl.is_nifti(anatomy_use): anatomy_use = nl.afni_copy(anatomy_use) epi_dsets_use = [] for dset in epi_dsets: if nl.is_nifti(dset): epi_dsets_use.append(nl.afni_copy(dset)) else: epi_dsets_use.append(dset) cmd = [ "align_epi_anat.py", "-epi2anat", "-anat_has_skull", "no", "-epi_strip", "3dAutomask", "-anat", anatomy_use, "-epi_base", "5", "-epi", epi_dsets_use[0] ] if len(epi_dsets_use) > 1: cmd += ['-child_epi'] + epi_dsets_use[1:] out = nl.run(cmd) for dset in epi_dsets: if nl.is_nifti(dset): dset_nifti = nl.nifti_copy(nl.prefix(dset) + '_al+orig') if dset_nifti and os.path.exists( dset_nifti) and dset_nifti.endswith( '.nii') and dset.endswith('.gz'): nl.run(['gzip', dset_nifti])
def mgz_to_nifti(filename,prefix=None,gzip=True): '''Convert ``filename`` to a NIFTI file using ``mri_convert``''' setup_freesurfer() if prefix==None: prefix = nl.prefix(filename) + '.nii' if gzip and not prefix.endswith('.gz'): prefix += '.gz' nl.run([os.path.join(freesurfer_home,'bin','mri_convert'),filename,prefix],products=prefix)
def skull_strip(dset, suffix='_ns', prefix=None, unifize=True): if prefix == None: prefix = nl.suffix(dset, suffix) nl.run([ '3dSkullStrip', '-input', dset, '-prefix', prefix, '-niter', '400', '-ld', '40' ], products=nl.suffix(dset, suffix))
def recon_all(subj_id, anatomies): '''Run the ``recon_all`` script''' if not environ_setup: setup_freesurfer() if isinstance(anatomies, basestring): anatomies = [anatomies] nl.run([ os.path.join(freesurfer_home, 'bin', 'recon-all'), '-all', '-subjid', subj_id ] + [['-i', anat] for anat in anatomies])
def skull_strip(dset,suffix='_ns',prefix=None,unifize=True): if prefix==None: prefix = nl.suffix(dset,suffix) nl.run([ '3dSkullStrip', '-input', dset, '-prefix', prefix, '-niter', '400', '-ld', '40' ],products=nl.suffix(dset,suffix))
def affine_align(dset_from,dset_to,skull_strip=True,mask=None,suffix='_aff',prefix=None,cost=None,epi=False,resample='wsinc5',grid_size=None,opts=[]): ''' interface to 3dAllineate to align anatomies and EPIs ''' dset_ss = lambda dset: os.path.split(nl.suffix(dset,'_ns'))[1] def dset_source(dset): if skull_strip==True or skull_strip==dset: return dset_ss(dset) else: return dset dset_affine = prefix if dset_affine==None: dset_affine = os.path.split(nl.suffix(dset_from,suffix))[1] dset_affine_mat_1D = nl.prefix(dset_affine) + '_matrix.1D' dset_affine_par_1D = nl.prefix(dset_affine) + '_params.1D' if os.path.exists(dset_affine): # final product already exists return for dset in [dset_from,dset_to]: if skull_strip==True or skull_strip==dset: nl.skull_strip(dset,'_ns') mask_use = mask if mask: # the mask was probably made in the space of the original dset_to anatomy, # which has now been cropped from the skull stripping. So the lesion mask # needs to be resampled to match the corresponding mask if skull_strip==True or skull_strip==dset_to: nl.run(['3dresample','-master',dset_u(dset_ss(dset)),'-inset',mask,'-prefix',nl.suffix(mask,'_resam')],products=nl.suffix(mask,'_resam')) mask_use = nl.suffix(mask,'_resam') all_cmd = [ '3dAllineate', '-prefix', dset_affine, '-base', dset_source(dset_to), '-source', dset_source(dset_from), '-source_automask', '-1Dmatrix_save', dset_affine_mat_1D, '-1Dparam_save',dset_affine_par_1D, '-autoweight', '-final',resample, '-cmass' ] + opts if grid_size: all_cmd += ['-newgrid',grid_size] if cost: all_cmd += ['-cost',cost] if epi: all_cmd += ['-EPI'] if mask: all_cmd += ['-emask', mask_use] nl.run(all_cmd,products=dset_affine)
def mgz_to_nifti(filename, prefix=None, gzip=True): '''Convert ``filename`` to a NIFTI file using ``mri_convert``''' setup_freesurfer() if prefix == None: prefix = nl.prefix(filename) + '.nii' if gzip and not prefix.endswith('.gz'): prefix += '.gz' nl.run([ os.path.join(freesurfer_home, 'bin', 'mri_convert'), filename, prefix ], products=prefix)
def qwarp_invert(warp_param_dset,output_dset,affine_1Dfile=None): '''inverts a qwarp (defined in ``warp_param_dset``) (and concatenates affine matrix ``affine_1Dfile`` if given) outputs the inverted warp + affine to ``output_dset``''' cmd = ['3dNwarpCat','-prefix',output_dset] if affine_1Dfile: cmd += ['-warp1','INV(%s)' % affine_1Dfile, '-warp2','INV(%s)' % warp_param_dset] else: cmd += ['-warp1','INV(%s)' % warp_param_dset] nl.run(cmd,products=output_dset)
def affine_apply(dset_from,affine_1D,master,affine_suffix='_aff',interp='NN',inverse=False,prefix=None): '''apply the 1D file from a previously aligned dataset Applies the matrix in ``affine_1D`` to ``dset_from`` and makes the final grid look like the dataset ``master`` using the interpolation method ``interp``. If ``inverse`` is True, will apply the inverse of ``affine_1D`` instead''' affine_1D_use = affine_1D if inverse: with tempfile.NamedTemporaryFile(delete=False) as temp: temp.write(subprocess.check_output(['cat_matvec',affine_1D,'-I'])) affine_1D_use = temp.name if prefix==None: prefix = nl.suffix(dset_from,affine_suffix) nl.run(['3dAllineate','-1Dmatrix_apply',affine_1D_use,'-input',dset_from,'-prefix',prefix,'-master',master,'-final',interp],products=prefix)
def roi_stats(mask, dset): out_dict = {} values = [{ 'Med': 'median', 'Min': 'min', 'Max': 'max', 'NZMean': 'nzmean', 'NZSum': 'nzsum', 'NZSigma': 'nzsigma', 'Mean': 'mean', 'Sigma': 'sigma', 'Mod': 'mode', 'NZcount': 'nzvoxels' }, { 'NZMod': 'nzmode', 'NZMed': 'nzmedian', 'NZMax': 'nzmax', 'NZMin': 'nzmin', 'Mean': 'mean' }] options = [[ '-nzmean', '-nzsum', '-nzvoxels', '-minmax', '-sigma', '-nzsigma', '-median', '-mode' ], ['-nzminmax', '-nzmedian', '-nzmode']] if not nl.dset_grids_equal((mask, dset)): i = nl.dset_info(dset) grid_hash = '_' + '_'.join( [str(x) for x in (i.voxel_size + i.voxel_dims)]) new_mask = nl.suffix(mask, grid_hash) if not os.path.exists(new_mask): nl.run([ "3dfractionize", "-template", dset, "-input", nl.calc(mask, "a", datum="short"), "-prefix", new_mask, "-preserve", "-clip", "0.2" ]) mask = new_mask for i in xrange(len(values)): cmd = ['3dROIstats', '-1Dformat', '-nobriklab', '-mask', mask ] + options[i] + [dset] out = subprocess.check_output(cmd).split('\n') header = [(values[i][x.split('_')[0]], int(x.split('_')[1])) for x in out[1].split()[1:]] for j in xrange(len(out) / 2 - 1): stats = [float(x) for x in out[(j + 1) * 2 + 1][1:].split()] for s in xrange(len(stats)): roi = header[s][1] stat_name = header[s][0] stat = stats[s] if roi not in out_dict: out_dict[roi] = {} out_dict[roi][stat_name] = stat return out_dict
def resample_dset(dset,template,prefix=None,resam='NN'): '''Resamples ``dset`` to the grid of ``template`` using resampling mode ``resam``. Default prefix is to suffix ``_resam`` at the end of ``dset`` Available resampling modes: :NN: Nearest Neighbor :Li: Linear :Cu: Cubic :Bk: Blocky ''' if prefix==None: prefix = nl.suffix(dset,'_resam') nl.run(['3dresample','-master',template,'-rmode',resam,'-prefix',prefix,'-inset',dset])
def volreg(dset,suffix='_volreg',base=3,tshift=3,dfile_suffix='_volreg.1D'): '''simple interface to 3dvolreg :suffix: suffix to add to ``dset`` for volreg'ed file :base: either a number or ``dset[#]`` of the base image to register to :tshift: if a number, then tshift ignoring that many images, if ``None`` then don't tshift :dfile_suffix: suffix to add to ``dset`` to save the motion parameters to ''' cmd = ['3dvolreg','-prefix',nl.suffix(dset,suffix),'-base',base,'-dfile',nl.prefix(dset)+dfile_suffix] if tshift: cmd += ['-tshift',tshift] cmd += [dset] nl.run(cmd,products=nl.suffix(dset,suffix))
def qwarp_epi(dset, align_subbrick=5, suffix='_qwal', prefix=None): '''aligns an EPI time-series using 3dQwarp Very expensive and not efficient at all, but it can produce pretty impressive alignment for EPI time-series with significant distortions due to motion''' info = nl.dset_info(dset) if info == None: nl.notify('Error reading dataset "%s"' % (dset), level=nl.level.error) return False if prefix == None: prefix = nl.suffix(dset, suffix) dset_sub = lambda x: '_tmp_qwarp_epi-%s_%d.nii.gz' % (nl.prefix(dset), x) try: align_dset = nl.suffix(dset_sub(align_subbrick), '_warp') nl.calc('%s[%d]' % (dset, align_subbrick), expr='a', prefix=align_dset, datum='float') for i in xrange(info.reps): if i != align_subbrick: nl.calc('%s[%d]' % (dset, i), expr='a', prefix=dset_sub(i), datum='float') nl.run([ '3dQwarp', '-nowarp', '-workhard', '-superhard', '-minpatch', '9', '-blur', '0', '-pear', '-nopenalty', '-base', align_dset, '-source', dset_sub(i), '-prefix', nl.suffix(dset_sub(i), '_warp') ], quiet=True) cmd = ['3dTcat', '-prefix', prefix] if info.TR: cmd += ['-tr', info.TR] if info.slice_timing: cmd += ['-tpattern', info.slice_timing] cmd += [nl.suffix(dset_sub(i), '_warp') for i in xrange(info.reps)] nl.run(cmd, quiet=True) except Exception as e: raise e finally: for i in xrange(info.reps): for suffix in ['', 'warp']: try: os.remove(nl.suffix(dset_sub(i), suffix)) except: pass
def bounding_box(dset): '''return the coordinates (in RAI) of the corners of a box enclosing the data in ``dset``''' o = nl.run(["3dAutobox", "-input", dset]) ijk_coords = re.findall(r'[xyz]=(\d+)\.\.(\d+)', o.output) from_rai = ijk_to_xyz(dset, [float(x[0]) for x in ijk_coords]) to_rai = ijk_to_xyz(dset, [float(x[1]) for x in ijk_coords]) return (from_rai, to_rai)
def qwarp_invert(warp_param_dset, output_dset, affine_1Dfile=None): '''inverts a qwarp (defined in ``warp_param_dset``) (and concatenates affine matrix ``affine_1Dfile`` if given) outputs the inverted warp + affine to ``output_dset``''' cmd = ['3dNwarpCat', '-prefix', output_dset] if affine_1Dfile: cmd += [ '-warp1', 'INV(%s)' % affine_1Dfile, '-warp2', 'INV(%s)' % warp_param_dset ] else: cmd += ['-warp1', 'INV(%s)' % warp_param_dset] nl.run(cmd, products=output_dset)
def resample_dset(dset, template, prefix=None, resam='NN'): '''Resamples ``dset`` to the grid of ``template`` using resampling mode ``resam``. Default prefix is to suffix ``_resam`` at the end of ``dset`` Available resampling modes: :NN: Nearest Neighbor :Li: Linear :Cu: Cubic :Bk: Blocky ''' if prefix == None: prefix = nl.suffix(dset, '_resam') nl.run([ '3dresample', '-master', template, '-rmode', resam, '-prefix', prefix, '-inset', dset ])
def bounding_box(dset): '''return the coordinates (in RAI) of the corners of a box enclosing the data in ``dset``''' o = nl.run(["3dAutobox","-input",dset]) ijk_coords = re.findall(r'[xyz]=(\d+)\.\.(\d+)',o.output) from_rai = ijk_to_xyz(dset,[float(x[0]) for x in ijk_coords]) to_rai = ijk_to_xyz(dset,[float(x[1]) for x in ijk_coords]) return (from_rai,to_rai)
def align_epi_anat(anatomy,epi_dsets,skull_strip_anat=True): ''' aligns epis to anatomy using ``align_epi_anat.py`` script :epi_dsets: can be either a string or list of strings of the epi child datasets :skull_strip_anat: if ``True``, ``anatomy`` will be skull-stripped using the default method The default output suffix is "_al" ''' if isinstance(epi_dsets,basestring): epi_dsets = [epi_dsets] if len(epi_dsets)==0: nl.notify('Warning: no epi alignment datasets given for anatomy %s!' % anatomy,level=nl.level.warning) return if all(os.path.exists(nl.suffix(x,'_al')) for x in epi_dsets): return anatomy_use = anatomy if skull_strip_anat: nl.skull_strip(anatomy,'_ns') anatomy_use = nl.suffix(anatomy,'_ns') inputs = [anatomy_use] + epi_dsets dset_products = lambda dset: [nl.suffix(dset,'_al'), nl.prefix(dset)+'_al_mat.aff12.1D', nl.prefix(dset)+'_tsh_vr_motion.1D'] products = nl.flatten([dset_products(dset) for dset in epi_dsets]) with nl.run_in_tmp(inputs,products): if nl.is_nifti(anatomy_use): anatomy_use = nl.afni_copy(anatomy_use) epi_dsets_use = [] for dset in epi_dsets: if nl.is_nifti(dset): epi_dsets_use.append(nl.afni_copy(dset)) else: epi_dsets_use.append(dset) cmd = ["align_epi_anat.py", "-epi2anat", "-anat_has_skull", "no", "-epi_strip", "3dAutomask","-anat", anatomy_use, "-epi_base", "5", "-epi", epi_dsets_use[0]] if len(epi_dsets_use)>1: cmd += ['-child_epi'] + epi_dsets_use[1:] out = nl.run(cmd) for dset in epi_dsets: if nl.is_nifti(dset): dset_nifti = nl.nifti_copy(nl.prefix(dset)+'_al+orig') if dset_nifti and os.path.exists(dset_nifti) and dset_nifti.endswith('.nii') and dset.endswith('.gz'): nl.run(['gzip',dset_nifti])
def run(self): '''runs 3dDeconvolve through the neural.utils.run shortcut''' out = nl.run(self.command_list(),products=self.prefix) if out and out.output: sds_list = re.findall(r'Stimulus: (.*?) *\n +h\[ 0\] norm\. std\. dev\. = +(\d+\.\d+)',out.output) self.stim_sds = {} for s in sds_list: self.stim_sds[s[0]] = float(s[1])
def inside_brain(stat_dset, atlas=None, p=0.001): '''calculates the percentage of voxels above a statistical threshold inside a brain mask vs. outside it if ``atlas`` is ``None``, it will try to find ``TT_N27``''' atlas = find_atlas(atlas) if atlas == None: return None mask_dset = nl.suffix(stat_dset, '_atlasfrac') nl.run([ '3dfractionize', '-template', nl.strip_subbrick(stat_dset), '-input', nl.calc([atlas], '1+step(a-100)', datum='short'), '-preserve', '-clip', '0.2', '-prefix', mask_dset ], products=mask_dset, quiet=True, stderr=None) s = nl.roi_stats(mask_dset, nl.thresh(stat_dset, p)) return 100.0 * s[2]['nzvoxels'] / (s[1]['nzvoxels'] + s[2]['nzvoxels'])
def fitness(individual): correlation = neural.run( individual[0], individual[1], individual[2], individual[3], individual[4], individual[5] ) return correlation
def qwarp_apply(dset_from, dset_warp, affine=None, warp_suffix='_warp', master='WARP', interp=None, prefix=None): '''applies the transform from a previous qwarp Uses the warp parameters from the dataset listed in ``dset_warp`` (usually the dataset name ends in ``_WARP``) to the dataset ``dset_from``. If a ``.1D`` file is given in the ``affine`` parameter, it will be applied simultaneously with the qwarp. If the parameter ``interp`` is given, will use as interpolation method, otherwise it will just use the default (currently wsinc5) Output dataset with have the ``warp_suffix`` suffix added to its name ''' out_dset = prefix if out_dset == None: out_dset = os.path.split(nl.suffix(dset_from, warp_suffix))[1] dset_from_info = nl.dset_info(dset_from) dset_warp_info = nl.dset_info(dset_warp) if (dset_from_info.orient != dset_warp_info.orient): # If the datasets are different orientations, the transform won't be applied correctly nl.run([ '3dresample', '-orient', dset_warp_info.orient, '-prefix', nl.suffix(dset_from, '_reorient'), '-inset', dset_from ], products=nl.suffix(dset_from, '_reorient')) dset_from = nl.suffix(dset_from, '_reorient') warp_opt = str(dset_warp) if affine: warp_opt += ' ' + affine cmd = ['3dNwarpApply', '-nwarp', warp_opt] cmd += ['-source', dset_from, '-master', master, '-prefix', out_dset] if interp: cmd += ['-interp', interp] nl.run(cmd, products=out_dset)
def qwarp_epi(dset,align_subbrick=5,suffix='_qwal',prefix=None): '''aligns an EPI time-series using 3dQwarp Very expensive and not efficient at all, but it can produce pretty impressive alignment for EPI time-series with significant distortions due to motion''' info = nl.dset_info(dset) if info==None: nl.notify('Error reading dataset "%s"' % (dset),level=nl.level.error) return False if prefix==None: prefix = nl.suffix(dset,suffix) dset_sub = lambda x: '_tmp_qwarp_epi-%s_%d.nii.gz' % (nl.prefix(dset),x) try: align_dset = nl.suffix(dset_sub(align_subbrick),'_warp') nl.calc('%s[%d]' % (dset,align_subbrick),expr='a',prefix=align_dset,datum='float') for i in xrange(info.reps): if i != align_subbrick: nl.calc('%s[%d]' % (dset,i),expr='a',prefix=dset_sub(i),datum='float') nl.run([ '3dQwarp', '-nowarp', '-workhard', '-superhard', '-minpatch', '9', '-blur', '0', '-pear', '-nopenalty', '-base', align_dset, '-source', dset_sub(i), '-prefix', nl.suffix(dset_sub(i),'_warp') ],quiet=True) cmd = ['3dTcat','-prefix',prefix] if info.TR: cmd += ['-tr',info.TR] if info.slice_timing: cmd += ['-tpattern',info.slice_timing] cmd += [nl.suffix(dset_sub(i),'_warp') for i in xrange(info.reps)] nl.run(cmd,quiet=True) except Exception as e: raise e finally: for i in xrange(info.reps): for suffix in ['','warp']: try: os.remove(nl.suffix(dset_sub(i),suffix)) except: pass
def temporal_snr(signal_dset, noise_dset, mask=None, prefix='temporal_snr.nii.gz'): '''Calculates temporal SNR by dividing average signal of ``signal_dset`` by SD of ``noise_dset``. ``signal_dset`` should be a dataset that contains the average signal value (i.e., nothing that has been detrended by removing the mean), and ``noise_dset`` should be a dataset that has all possible known signal fluctuations (e.g., task-related effects) removed from it (the residual dataset from a deconvolve works well)''' for d in [('mean', signal_dset), ('stdev', noise_dset)]: new_d = nl.suffix(d[1], '_%s' % d[0]) cmd = ['3dTstat', '-%s' % d[0], '-prefix', new_d] if mask: cmd += ['-mask', mask] cmd += [d[1]] nl.run(cmd, products=new_d) nl.calc([nl.suffix(signal_dset, '_mean'), nl.suffix(noise_dset, '_stdev')], 'a/b', prefix=prefix)
def skullstrip_template(dset,template,prefix=None,suffix=None,dilate=0): '''Takes the raw anatomy ``dset``, aligns it to a template brain, and applies a templated skullstrip. Should produce fairly reliable skullstrips as long as there is a decent amount of normal brain and the overall shape of the brain is normal-ish''' if suffix==None: suffix = '_sstemplate' if prefix==None: prefix = nl.suffix(dset,suffix) if not os.path.exists(prefix): with nl.notify('Running template-based skull-strip on %s' % dset): dset = os.path.abspath(dset) template = os.path.abspath(template) tmp_dir = tempfile.mkdtemp() cwd = os.getcwd() with nl.run_in(tmp_dir): nl.affine_align(template,dset,skull_strip=None,cost='mi',opts=['-nmatch','100%']) nl.run(['3dQwarp','-minpatch','20','-penfac','10','-noweight','-source',nl.suffix(template,'_aff'),'-base',dset,'-prefix',nl.suffix(template,'_qwarp')],products=nl.suffix(template,'_qwarp')) info = nl.dset_info(nl.suffix(template,'_qwarp')) max_value = info.subbricks[0]['max'] nl.calc([dset,nl.suffix(template,'_qwarp')],'a*step(b-%f*0.05)'%max_value,prefix) shutil.move(prefix,cwd) shutil.rmtree(tmp_dir)
def outcount(dset, fraction=0.1): '''gets outlier count and returns ``(list of proportion of outliers by timepoint,total percentage of outlier time points)''' polort = nl.auto_polort(dset) info = nl.dset_info(dset) o = nl.run( ['3dToutcount', '-fraction', '-automask', '-polort', polort, dset], stderr=None, quiet=None) if o.return_code == 0 and o.output: oc = [float(x) for x in o.output.split('\n') if x.strip() != ''] binary_outcount = [x < fraction for x in oc] perc_outliers = 1 - (sum(binary_outcount) / float(info.reps)) return (oc, perc_outliers)
def qwarp_apply(dset_from,dset_warp,affine=None,warp_suffix='_warp',master='WARP',interp=None,prefix=None): '''applies the transform from a previous qwarp Uses the warp parameters from the dataset listed in ``dset_warp`` (usually the dataset name ends in ``_WARP``) to the dataset ``dset_from``. If a ``.1D`` file is given in the ``affine`` parameter, it will be applied simultaneously with the qwarp. If the parameter ``interp`` is given, will use as interpolation method, otherwise it will just use the default (currently wsinc5) Output dataset with have the ``warp_suffix`` suffix added to its name ''' out_dset = prefix if out_dset==None: out_dset = os.path.split(nl.suffix(dset_from,warp_suffix))[1] dset_from_info = nl.dset_info(dset_from) dset_warp_info = nl.dset_info(dset_warp) if(dset_from_info.orient!=dset_warp_info.orient): # If the datasets are different orientations, the transform won't be applied correctly nl.run(['3dresample','-orient',dset_warp_info.orient,'-prefix',nl.suffix(dset_from,'_reorient'),'-inset',dset_from],products=nl.suffix(dset_from,'_reorient')) dset_from = nl.suffix(dset_from,'_reorient') warp_opt = str(dset_warp) if affine: warp_opt += ' ' + affine cmd = [ '3dNwarpApply', '-nwarp', warp_opt] cmd += [ '-source', dset_from, '-master',master, '-prefix', out_dset ] if interp: cmd += ['-interp',interp] nl.run(cmd,products=out_dset)
def volreg(dset, suffix='_volreg', base=3, tshift=3, dfile_suffix='_volreg.1D'): '''simple interface to 3dvolreg :suffix: suffix to add to ``dset`` for volreg'ed file :base: either a number or ``dset[#]`` of the base image to register to :tshift: if a number, then tshift ignoring that many images, if ``None`` then don't tshift :dfile_suffix: suffix to add to ``dset`` to save the motion parameters to ''' cmd = [ '3dvolreg', '-prefix', nl.suffix(dset, suffix), '-base', base, '-dfile', nl.prefix(dset) + dfile_suffix ] if tshift: cmd += ['-tshift', tshift] cmd += [dset] nl.run(cmd, products=nl.suffix(dset, suffix))
def ijk_to_xyz(dset,ijk): '''convert the dset indices ``ijk`` to RAI coordinates ``xyz``''' i = nl.dset_info(dset) orient_codes = [int(x) for x in nl.run(['@AfniOrient2RAImap',i.orient]).output.split()] orient_is = [abs(x)-1 for x in orient_codes] rai = [] for rai_i in xrange(3): ijk_i = orient_is[rai_i] if orient_codes[rai_i] > 0: rai.append(ijk[ijk_i]*i.voxel_size[rai_i] + i.spatial_from[rai_i]) else: rai.append(i.spatial_to[rai_i] - ijk[ijk_i]*i.voxel_size[rai_i]) return rai
def driver_send(command, hostname=None, wait=0.2): '''Send a command (or ``list`` of commands) to AFNI at ``hostname`` (defaults to local host) Requires plugouts enabled (open afni with ``-yesplugouts`` or set ``AFNI_YESPLUGOUTS = YES`` in ``.afnirc``) If ``wait`` is not ``None``, will automatically sleep ``wait`` seconds after sending the command (to make sure it took effect)''' cmd = ['plugout_drive'] if hostname: cmd += ['-host', hostname] if isinstance(command, basestring): command = [command] cmd += [['-com', x] for x in command] + ['-quit'] o = nl.run(cmd, quiet=None, stderr=None) if wait != None: time.sleep(wait)
def unpack_archive(fname, out_dir): '''unpacks the archive file ``fname`` and reconstructs datasets into ``out_dir`` Datasets are reconstructed and auto-named using :meth:`create_dset`. The raw directories that made the datasets are archive with the dataset name suffixed by ``tgz``, and any other files found in the archive are put into ``other_files.tgz``''' with nl.notify('Unpacking archive %s' % fname): tmp_dir = tempfile.mkdtemp() tmp_unpack = os.path.join(tmp_dir, 'unpack') os.makedirs(tmp_unpack) nl.utils.unarchive(fname, tmp_unpack) reconstruct_files(tmp_unpack) out_dir = os.path.abspath(out_dir) if not os.path.exists(out_dir): os.makedirs(out_dir) if not os.path.exists(tmp_unpack + '-sorted'): return with nl.run_in(tmp_unpack + '-sorted'): for fname in glob.glob('*.nii'): nl.run(['gzip', fname]) for fname in glob.glob('*.nii.gz'): new_file = os.path.join(out_dir, fname) if not os.path.exists(new_file): shutil.move(fname, new_file) raw_out = os.path.join(out_dir, 'raw') if not os.path.exists(raw_out): os.makedirs(raw_out) for rawdir in os.listdir('.'): rawdir_tgz = os.path.join(raw_out, rawdir + '.tgz') if not os.path.exists(rawdir_tgz): with tarfile.open(rawdir_tgz, 'w:gz') as tgz: tgz.add(rawdir) if len(os.listdir(tmp_unpack)) != 0: # There are still raw files left with tarfile.open(os.path.join(raw_out, 'other_files.tgz'), 'w:gz') as tgz: tgz.add(tmp_unpack) shutil.rmtree(tmp_dir)
def affine_apply(dset_from, affine_1D, master, affine_suffix='_aff', interp='NN', inverse=False, prefix=None): '''apply the 1D file from a previously aligned dataset Applies the matrix in ``affine_1D`` to ``dset_from`` and makes the final grid look like the dataset ``master`` using the interpolation method ``interp``. If ``inverse`` is True, will apply the inverse of ``affine_1D`` instead''' affine_1D_use = affine_1D if inverse: with tempfile.NamedTemporaryFile(delete=False) as temp: temp.write(subprocess.check_output(['cat_matvec', affine_1D, '-I'])) affine_1D_use = temp.name if prefix == None: prefix = nl.suffix(dset_from, affine_suffix) nl.run([ '3dAllineate', '-1Dmatrix_apply', affine_1D_use, '-input', dset_from, '-prefix', prefix, '-master', master, '-final', interp ], products=nl.suffix(dset_from, affine_suffix))
def unpack_archive(fname,out_dir): '''unpacks the archive file ``fname`` and reconstructs datasets into ``out_dir`` Datasets are reconstructed and auto-named using :meth:`create_dset`. The raw directories that made the datasets are archive with the dataset name suffixed by ``tgz``, and any other files found in the archive are put into ``other_files.tgz``''' with nl.notify('Unpacking archive %s' % fname): tmp_dir = tempfile.mkdtemp() tmp_unpack = os.path.join(tmp_dir,'unpack') os.makedirs(tmp_unpack) nl.utils.unarchive(fname,tmp_unpack) reconstruct_files(tmp_unpack) out_dir = os.path.abspath(out_dir) if not os.path.exists(out_dir): os.makedirs(out_dir) if not os.path.exists(tmp_unpack+'-sorted'): return with nl.run_in(tmp_unpack+'-sorted'): for fname in glob.glob('*.nii'): nl.run(['gzip',fname]) for fname in glob.glob('*.nii.gz'): new_file = os.path.join(out_dir,fname) if not os.path.exists(new_file): shutil.move(fname,new_file) raw_out = os.path.join(out_dir,'raw') if not os.path.exists(raw_out): os.makedirs(raw_out) for rawdir in os.listdir('.'): rawdir_tgz = os.path.join(raw_out,rawdir+'.tgz') if not os.path.exists(rawdir_tgz): with tarfile.open(rawdir_tgz,'w:gz') as tgz: tgz.add(rawdir) if len(os.listdir(tmp_unpack))!=0: # There are still raw files left with tarfile.open(os.path.join(raw_out,'other_files.tgz'),'w:gz') as tgz: tgz.add(tmp_unpack) shutil.rmtree(tmp_dir)
def start_server(self): c = zmq.Context() sock = c.socket(zmq.REP) sock.bind('tcp://*:%s' % self.port) try: while True: msg = sock.recv() try: obj = json.loads(msg) if 'key' not in obj or obj['key'] != _key: raise ValueError if self.password: if 'password' not in obj or 'time' not in obj: raise ValueError if nl.hash_str(self.password + str(obj['time'])) != obj['password']: raise ValueError except ValueError: # not a valid packet sock.send('ERR') continue else: if 'task' in obj: if obj['task'] == 'info': sock.send( json.dumps({ 'name': self.name, 'address': self.address, 'port': self.port })) continue if obj['task'] == 'job': print 'Being asked to run command: ' + str( obj['command']) cmd = [obj['command'], None, '.'] if 'products' in obj: cmd[1] = obj['products'] if 'working_directory' in obj: cmd[2] = obj['working_directory'] output = nl.run(*cmd) sock.send(json.dumps({'output': output.__dict__()})) continue sock.send('OK') except KeyboardInterrupt: c.destroy()
def skull_strip(dset, suffix='_ns', prefix=None, unifize=True): ''' use bet to strip skull from given anatomy ''' # should add options to use betsurf and T1/T2 in the future # Since BET fails on weirdly distributed datasets, I added 3dUnifize in... I realize this makes this dependent on AFNI. Sorry, :) if prefix == None: prefix = nl.suffix(dset, suffix) unifize_dset = nl.suffix(dset, '_u') cmd = bet2 if bet2 else 'bet2' if unifize: info = nl.dset_info(dset) if info == None: nl.notify('Error: could not read info for dset %s' % dset, level=nl.level.error) return False cmd = os.path.join(fsl_dir, cmd) if fsl_dir else cmd cutoff_value = nl.max(dset) * 0.05 nl.run([ '3dUnifize', '-prefix', unifize_dset, nl.calc(dset, 'step(a-%f)*a' % cutoff_value) ], products=unifize_dset) else: unifize_dset = dset nl.run([cmd, unifize_dset, prefix, '-w', 0.5], products=prefix)
def ijk_to_xyz(dset, ijk): '''convert the dset indices ``ijk`` to RAI coordinates ``xyz``''' i = nl.dset_info(dset) orient_codes = [ int(x) for x in nl.run(['@AfniOrient2RAImap', i.orient]).output.split() ] orient_is = [abs(x) - 1 for x in orient_codes] rai = [] for rai_i in xrange(3): ijk_i = orient_is[rai_i] if orient_codes[rai_i] > 0: rai.append(ijk[ijk_i] * i.voxel_size[rai_i] + i.spatial_from[rai_i]) else: rai.append(i.spatial_to[rai_i] - ijk[ijk_i] * i.voxel_size[rai_i]) return rai
def calc(dsets,expr,prefix=None,datum=None): if isinstance(dsets,basestring): dsets = [dsets] if prefix: cmd = ['3dcalc'] else: cmd = ['3dcalc('] for i in xrange(len(dsets)): cmd += ['-%s'% chr(97+i),dsets[i]] cmd += ['-expr',expr] if datum: cmd += ['-datum',datum] if prefix: cmd += ['-prefix',prefix] return nl.run(cmd,products=prefix) else: cmd += [')'] return ' '.join(cmd)
def calc(dsets, expr, prefix=None, datum=None): if isinstance(dsets, basestring): dsets = [dsets] if prefix: cmd = ['3dcalc'] else: cmd = ['3dcalc('] for i in xrange(len(dsets)): cmd += ['-%s' % chr(97 + i), dsets[i]] cmd += ['-expr', expr] if datum: cmd += ['-datum', datum] if prefix: cmd += ['-prefix', prefix] return nl.run(cmd, products=prefix) else: cmd += [')'] return ' '.join(cmd)
def start_server(self): c = zmq.Context() sock = c.socket(zmq.REP) sock.bind('tcp://*:%s' % self.port) try: while True: msg = sock.recv() try: obj = json.loads(msg) if 'key' not in obj or obj['key']!=_key: raise ValueError if self.password: if 'password' not in obj or 'time' not in obj: raise ValueError if nl.hash_str(self.password + str(obj['time']))!= obj['password']: raise ValueError except ValueError: # not a valid packet sock.send('ERR') continue else: if 'task' in obj: if obj['task']=='info': sock.send(json.dumps({'name':self.name,'address':self.address,'port':self.port})) continue if obj['task']=='job': print 'Being asked to run command: ' + str(obj['command']) cmd = [obj['command'],None,'.'] if 'products' in obj: cmd[1] = obj['products'] if 'working_directory' in obj: cmd[2] = obj['working_directory'] output = nl.run(*cmd) sock.send(json.dumps({'output':output.__dict__()})) continue sock.send('OK') except KeyboardInterrupt: c.destroy()
def rsync_remote(pi, verify=False): with nl.notify('rsync\'ing data for PI %s' % pi): opts = c.rsync_options if verify: opts += 'v' nl.notify( 'If running as a non-administrator, you may be prompted for the server (%s) password' % c.server_name) o = nl.run([ c.rsync, opts, '-e', 'ssh -i %s' % c.server_id, '%s/%s' % (c.server_name, pi), import_location ]) if verify: if o.return_code != 0: nl.notify('Error: Rsync returned status code of %d' % o.return_code, level=nl.level.error) else: nl.notify('Rsync completed successfully') if o.output: nl.notify('Output:\n' + o.output)
def mask_average(dset,mask): '''Returns average of voxels in ``dset`` within non-zero voxels of ``mask``''' o = nl.run(['3dmaskave','-q','-mask',mask,dset]) if o: return float(o.output.split()[-1])
def cluster(dset,min_distance,min_cluster_size,prefix): nl.run(['3dmerge','-1clust',min_distance,min_cluster_size,'-prefix',prefix,dset],products=prefix)
def affine_align(dset_from, dset_to, skull_strip=True, mask=None, suffix='_aff', prefix=None, cost=None, epi=False, resample='wsinc5', grid_size=None, opts=[]): ''' interface to 3dAllineate to align anatomies and EPIs ''' dset_ss = lambda dset: os.path.split(nl.suffix(dset, '_ns'))[1] def dset_source(dset): if skull_strip == True or skull_strip == dset: return dset_ss(dset) else: return dset dset_affine = prefix if dset_affine == None: dset_affine = os.path.split(nl.suffix(dset_from, suffix))[1] dset_affine_mat_1D = nl.prefix(dset_affine) + '_matrix.1D' dset_affine_par_1D = nl.prefix(dset_affine) + '_params.1D' if os.path.exists(dset_affine): # final product already exists return for dset in [dset_from, dset_to]: if skull_strip == True or skull_strip == dset: nl.skull_strip(dset, '_ns') mask_use = mask if mask: # the mask was probably made in the space of the original dset_to anatomy, # which has now been cropped from the skull stripping. So the lesion mask # needs to be resampled to match the corresponding mask if skull_strip == True or skull_strip == dset_to: nl.run([ '3dresample', '-master', dset_u(dset_ss(dset)), '-inset', mask, '-prefix', nl.suffix(mask, '_resam') ], products=nl.suffix(mask, '_resam')) mask_use = nl.suffix(mask, '_resam') all_cmd = [ '3dAllineate', '-prefix', dset_affine, '-base', dset_source(dset_to), '-source', dset_source(dset_from), '-1Dmatrix_save', dset_affine_mat_1D, '-1Dparam_save', dset_affine_par_1D, '-autoweight', '-final', resample, '-cmass' ] + opts if grid_size: all_cmd += ['-newgrid', grid_size] if cost: all_cmd += ['-cost', cost] if epi: all_cmd += ['-EPI'] if mask: all_cmd += ['-emask', mask_use] nl.run(all_cmd, products=dset_affine)
def segment(dset): nl.run([fast, dset])
def smooth_decon_to_fwhm(decon,fwhm,cache=True): '''takes an input :class:`Decon` object and uses ``3dBlurToFWHM`` to make the output as close as possible to ``fwhm`` returns the final measured fwhm. If ``cache`` is ``True``, will save the blurred input file (and use it again in the future)''' if os.path.exists(decon.prefix): return blur_dset = lambda dset: nl.suffix(dset,'_smooth_to_%.2f' % fwhm) with nl.notify('Running smooth_decon_to_fwhm analysis (with %.2fmm blur)' % fwhm): tmpdir = tempfile.mkdtemp() try: cwd = os.getcwd() random_files = [re.sub(r'\[\d+\]$','',str(x)) for x in nl.flatten([x for x in decon.__dict__.values() if isinstance(x,basestring) or isinstance(x,list)]+[x.values() for x in decon.__dict__.values() if isinstance(x,dict)])] files_to_copy = [x for x in random_files if os.path.exists(x) and x[0]!='/'] files_to_copy += [blur_dset(dset) for dset in decon.input_dsets if os.path.exists(blur_dset(dset))] # copy crap for file in files_to_copy: try: shutil.copytree(file,tmpdir) except OSError as e: shutil.copy(file,tmpdir) shutil.copy(file,tmpdir) copyback_files = [decon.prefix,decon.errts] with nl.run_in(tmpdir): if os.path.exists(decon.prefix): os.remove(decon.prefix) # Create the blurred inputs (or load from cache) if cache and all([os.path.exists(os.path.join(cwd,blur_dset(dset))) for dset in decon.input_dsets]): # Everything is already cached... nl.notify('Using cache\'d blurred datasets') else: # Need to make them from scratch with nl.notify('Creating blurred datasets'): old_errts = decon.errts decon.errts = 'residual.nii.gz' decon.prefix = os.path.basename(decon.prefix) # Run once in place to get the residual dataset decon.run() running_reps = 0 for dset in decon.input_dsets: info = nl.dset_info(dset) residual_dset = nl.suffix(dset,'_residual') nl.run(['3dbucket','-prefix',residual_dset,'%s[%d..%d]'%(decon.errts,running_reps,running_reps+info.reps-1)],products=residual_dset) cmd = ['3dBlurToFWHM','-quiet','-input',dset,'-blurmaster',residual_dset,'-prefix',blur_dset(dset),'-FWHM',fwhm] if decon.mask: if decon.mask=='auto': cmd += ['-automask'] else: cmd += ['-mask',decon.mask] nl.run(cmd,products=blur_dset(dset)) running_reps += info.reps if cache: copyback_files.append(blur_dset(dset)) decon.errts = old_errts decon.input_dsets = [blur_dset(dset) for dset in decon.input_dsets] for d in [decon.prefix,decon.errts]: if os.path.exists(d): try: os.remove(d) except: pass decon.run() for copyfile in copyback_files: if os.path.exists(copyfile): shutil.copy(copyfile,cwd) else: nl.notify('Warning: deconvolve did not produce expected file %s' % decon.prefix,level=nl.level.warning) except: raise finally: shutil.rmtree(tmpdir,True)
def value_at_coord(dset,coords): '''returns value at specified coordinate in ``dset``''' return nl.numberize(nl.run(['3dmaskave','-q','-dbox'] + list(coords) + [dset],stderr=None).output)
def qwarp_align(dset_from, dset_to, skull_strip=True, mask=None, affine_suffix='_aff', suffix='_qwarp', prefix=None): '''aligns ``dset_from`` to ``dset_to`` using 3dQwarp Will run ``3dSkullStrip`` (unless ``skull_strip`` is ``False``), ``3dUnifize``, ``3dAllineate``, and then ``3dQwarp``. This method will add suffixes to the input dataset for the intermediate files (e.g., ``_ss``, ``_u``). If those files already exist, it will assume they were intelligently named, and use them as is :skull_strip: If True/False, turns skull-stripping of both datasets on/off. If a string matching ``dset_from`` or ``dset_to``, will only skull-strip the given dataset :mask: Applies the given mask to the alignment. Because of the nature of the alignment algorithms, the mask is **always** applied to the ``dset_to``. If this isn't what you want, you need to reverse the transform and re-apply it (e.g., using :meth:`qwarp_invert` and :meth:`qwarp_apply`). If the ``dset_to`` dataset is skull-stripped, the mask will also be resampled to match the ``dset_to`` grid. :affine_suffix: Suffix applied to ``dset_from`` to name the new dataset, as well as the ``.1D`` file. :suffix: Suffix applied to the final ``dset_from`` dataset. An additional file with the additional suffix ``_WARP`` will be created containing the parameters (e.g., with the default ``_qwarp`` suffix, the parameters will be in a file with the suffix ``_qwarp_WARP``) :prefix: Alternatively to ``suffix``, explicitly give the full output filename The output affine dataset and 1D, as well as the output of qwarp are named by adding the given suffixes (``affine_suffix`` and ``qwarp_suffix``) to the ``dset_from`` file If ``skull_strip`` is a string instead of ``True``/``False``, it will only skull strip the given dataset instead of both of them # TODO: currently does not work with +tlrc datasets because the filenames get mangled ''' dset_ss = lambda dset: os.path.split(nl.suffix(dset, '_ns'))[1] dset_u = lambda dset: os.path.split(nl.suffix(dset, '_u'))[1] def dset_source(dset): if skull_strip == True or skull_strip == dset: return dset_ss(dset) else: return dset dset_affine = os.path.split(nl.suffix(dset_from, affine_suffix))[1] dset_affine_1D = nl.prefix(dset_affine) + '.1D' dset_qwarp = prefix if dset_qwarp == None: dset_qwarp = os.path.split(nl.suffix(dset_from, suffix))[1] if os.path.exists(dset_qwarp): # final product already exists return affine_align(dset_from, dset_to, skull_strip, mask, affine_suffix) for dset in [dset_from, dset_to]: nl.run([ '3dUnifize', '-prefix', dset_u(dset_source(dset)), '-input', dset_source(dset) ], products=[dset_u(dset_source(dset))]) mask_use = mask if mask: # the mask was probably made in the space of the original dset_to anatomy, # which has now been cropped from the skull stripping. So the lesion mask # needs to be resampled to match the corresponding mask if skull_strip == True or skull_strip == dset_to: nl.run([ '3dresample', '-master', dset_u(dset_ss(dset)), '-inset', mask, '-prefix', nl.suffix(mask, '_resam') ], products=nl.suffix(mask, '_resam')) mask_use = nl.suffix(mask, '_resam') warp_cmd = [ '3dQwarp', '-prefix', dset_qwarp, '-duplo', '-useweight', '-blur', '0', '3', '-iwarp', '-base', dset_u(dset_source(dset_to)), '-source', dset_affine ] if mask: warp_cmd += ['-emask', mask_use] nl.run(warp_cmd, products=dset_qwarp)
def blur(dset,fwhm,prefix): nl.run(['3dmerge','-1blur_fwhm',fwhm,'-prefix',prefix,dset],products=prefix)
def value_at_coord(dset, coords): '''returns value at specified coordinate in ``dset``''' return nl.numberize( nl.run(['3dmaskave', '-q', '-dbox'] + list(coords) + [dset], stderr=None).output)
def qwarp_align(dset_from,dset_to,skull_strip=True,mask=None,affine_suffix='_aff',suffix='_qwarp',prefix=None): '''aligns ``dset_from`` to ``dset_to`` using 3dQwarp Will run ``3dSkullStrip`` (unless ``skull_strip`` is ``False``), ``3dUnifize``, ``3dAllineate``, and then ``3dQwarp``. This method will add suffixes to the input dataset for the intermediate files (e.g., ``_ss``, ``_u``). If those files already exist, it will assume they were intelligently named, and use them as is :skull_strip: If True/False, turns skull-stripping of both datasets on/off. If a string matching ``dset_from`` or ``dset_to``, will only skull-strip the given dataset :mask: Applies the given mask to the alignment. Because of the nature of the alignment algorithms, the mask is **always** applied to the ``dset_to``. If this isn't what you want, you need to reverse the transform and re-apply it (e.g., using :meth:`qwarp_invert` and :meth:`qwarp_apply`). If the ``dset_to`` dataset is skull-stripped, the mask will also be resampled to match the ``dset_to`` grid. :affine_suffix: Suffix applied to ``dset_from`` to name the new dataset, as well as the ``.1D`` file. :suffix: Suffix applied to the final ``dset_from`` dataset. An additional file with the additional suffix ``_WARP`` will be created containing the parameters (e.g., with the default ``_qwarp`` suffix, the parameters will be in a file with the suffix ``_qwarp_WARP``) :prefix: Alternatively to ``suffix``, explicitly give the full output filename The output affine dataset and 1D, as well as the output of qwarp are named by adding the given suffixes (``affine_suffix`` and ``qwarp_suffix``) to the ``dset_from`` file If ``skull_strip`` is a string instead of ``True``/``False``, it will only skull strip the given dataset instead of both of them # TODO: currently does not work with +tlrc datasets because the filenames get mangled ''' dset_ss = lambda dset: os.path.split(nl.suffix(dset,'_ns'))[1] dset_u = lambda dset: os.path.split(nl.suffix(dset,'_u'))[1] def dset_source(dset): if skull_strip==True or skull_strip==dset: return dset_ss(dset) else: return dset dset_affine = os.path.split(nl.suffix(dset_from,affine_suffix))[1] dset_affine_1D = nl.prefix(dset_affine) + '.1D' dset_qwarp = prefix if dset_qwarp==None: dset_qwarp = os.path.split(nl.suffix(dset_from,suffix))[1] if os.path.exists(dset_qwarp): # final product already exists return affine_align(dset_from,dset_to,skull_strip,mask,affine_suffix) for dset in [dset_from,dset_to]: nl.run([ '3dUnifize', '-prefix', dset_u(dset_source(dset)), '-input', dset_source(dset) ],products=[dset_u(dset_source(dset))]) mask_use = mask if mask: # the mask was probably made in the space of the original dset_to anatomy, # which has now been cropped from the skull stripping. So the lesion mask # needs to be resampled to match the corresponding mask if skull_strip==True or skull_strip==dset_to: nl.run(['3dresample','-master',dset_u(dset_ss(dset)),'-inset',mask,'-prefix',nl.suffix(mask,'_resam')],products=nl.suffix(mask,'_resam')) mask_use = nl.suffix(mask,'_resam') warp_cmd = [ '3dQwarp', '-prefix', dset_qwarp, '-duplo', '-useweight', '-blur', '0', '3', '-iwarp', '-base', dset_u(dset_source(dset_to)), '-source', dset_affine ] if mask: warp_cmd += ['-emask', mask_use] nl.run(warp_cmd,products=dset_qwarp)
def tshift(dset,suffix='_tshift',initial_ignore=3): nl.run(['3dTshift','-prefix',nl.suffix(dset,suffix),'-ignore',initial_ignore,dset],products=nl.suffix(dset,suffix))