def _WarpImage(dwimask, vol, xfm): if dwimask: unu('3op', 'ifelse', dwimask, vol, '0', '-o', vol) volwarped = vol.stem + '-warped.nrrd' WarpImageMultiTransform('3', vol, volwarped, '-R', vol, xfm) return volwarped
def main(self): hdr = unu('head', self.nrrd)[:-1] new_origin = centered_origin(hdr) unu('save', '-e', 'gzip', '-f', 'nrrd', '-i', self.nrrd, '-o', self.out) replace_line_in_file( self.out, "space origin: ", "space origin: (%s, %s, %s)\n" % tuple(new_origin))
def main(self): with TemporaryDirectory() as tmpdir: tmpdir = local.path(tmpdir) bse = tmpdir / "maskedbse.nrrd" t2masked = tmpdir / "maskedt2.nrrd" t2inbse = tmpdir / "t2inbse.nrrd" epiwarp = tmpdir / "epiwarp.nii.gz" t2tobse_rigid = tmpdir / "t2tobse_rigid" logging.info('1. Extract and mask the DWI b0') bse_py('-m', self.dwimask ,'-i', self.dwi ,'-o', bse) logging.info("2. Mask the T2") unu("3op", "ifelse", self.t2mask, self.t2, "0", "-o", t2masked) logging.info( "3. Compute a rigid registration from the T2 to the DWI baseline") antsRegistrationSyN_sh("-d", "3" ,"-f", bse ,"-m", t2masked ,"-t", "r" ,"-o", tmpdir / "t2tobse_rigid") antsApplyTransforms("-d", "3" ,"-i", t2masked ,"-o", t2inbse ,"-r", bse ,"-t", tmpdir / "t2tobse_rigid0GenericAffine.mat") logging.info("4. Compute 1d nonlinear registration from the DWI to the T2 along the phase direction") moving = bse fixed = t2inbse pre = tmpdir / "epi" dwiepi = tmpdir / "dwiepi"+getext(self.out) antsRegistration("-d", "3" ,"-m", "cc["+fixed+","+moving+",1,2]" ,"-t", "SyN[0.25,3,0]" ,"-c", "50x50x10" ,"-f", "4x2x1" , "-s", "2x1x0" ,"--restrict-deformation", "0x1x0" ,"-v", "1" ,"-o", pre) local.path(pre+"0Warp.nii.gz").move(epiwarp) logging.info("5. Apply warp to the DWI") antsApplyTransformsDWI_sh(self.dwi, self.dwimask, epiwarp, dwiepi) if getext(dwiepi) == '.nhdr': unu("save","-e","gzip","-f","nrrd","-i",dwiepi,self.out) else: dwiepi.move(self.out) if self.debug: tmpdir.move("epidebug-"+getpid())
def main(self): if not self.force and self.out.exists(): logging.error("'{}' already exists, use '--force' to force overwrite.".format(self.out)) sys.exit(1) with TemporaryDirectory() as tmpdir: tmpdir = local.path(tmpdir) bse = tmpdir / "maskedbse.nrrd" t2masked = tmpdir / "maskedt2.nrrd" t2inbse = tmpdir / "t2inbse.nrrd" epiwarp = tmpdir / "epiwarp.nii.gz" t2tobse_rigid = tmpdir / "t2tobse_rigid" logging.info('1. Extract and mask the DWI b0') bse_py('-m', self.dwimask, '-i', self.dwi, '-o', bse) logging.info("2. Mask the T2") unu("3op", "ifelse", self.t2mask, self.t2, "0", "-o", t2masked) logging.info( "3. Compute a rigid registration from the T2 to the DWI baseline") antsRegistrationSyN_sh("-d", "3", "-f", bse, "-m", t2masked, "-t", "r", "-o", tmpdir / "t2tobse_rigid") antsApplyTransforms("-d", "3", "-i", t2masked, "-o", t2inbse, "-r", bse, "-t", tmpdir / "t2tobse_rigid0GenericAffine.mat") logging.info( "4. Compute 1d nonlinear registration from the DWI to the T2 along the phase direction") moving = bse fixed = t2inbse pre = tmpdir / "epi" dwiepi = tmpdir / ("dwiepi" + ''.join(self.out.suffixes)) antsRegistration("-d", "3", "-m", "cc[" + str(fixed) + "," + str(moving) + ",1,2]", "-t", "SyN[0.25,3,0]", "-c", "50x50x10", "-f", "4x2x1", "-s", "2x1x0", "--restrict-deformation", "0x1x0", "-v", "1", "-o", pre) local.path(str(pre) + "0Warp.nii.gz").move(epiwarp) logging.info("5. Apply warp to the DWI") antsApplyTransformsDWI_py('-i', self.dwi, '-m', self.dwimask, '-t', epiwarp, '-o', dwiepi) if '.nhdr' in dwiepi.suffixes: unu("save", "-e", "gzip", "-f", "nrrd", "-i", dwiepi, self.out) else: dwiepi.move(self.out) if self.debug: tmpdir.copy(self.out.dirname / ("epidebug-" + str(getpid())))
def test_DWIConvert(): with TemporaryDirectory() as tmpdir: fsl = tmpdir / 'dwi.nii.gz' nrrd = tmpdir / 'dwi.nrrd' nrrdFromFSl = tmpdir / 'dwi-from-fsl.nrrd' run(dwidicoms, fsl) run(dwidicoms, nrrd) run(fsl, nrrdfromFsl) output = unu('diff', nrrd, nrrdFromFSl) assert not 'differ' in output
def nrrd_get_b0_index(dwi): dwi = local.path(dwi) hdr = unu("head", dwi)[:-1] def norm(vector): return sum([v**2 for v in vector]) bval = get_bval(hdr) bvals = [norm(gdir) * bval for gdir in get_grad_dirs(hdr)] idx, min_bval = min(enumerate(bvals), key=operator.itemgetter(1)) logger.info("Found B0 of " + str(min_bval) + " at index " + str(idx)) return idx
def main(self): hdr = unu("head", self.dwi)[:-1] idx = get_b0_index(hdr) slicecmd = unu["slice", "-a", "3", "-p", str(idx), "-i", self.dwi] gzipcmd = unu["save", "-e", "gzip", "-f", "nrrd", "-o", self.out] if self.dwimask: maskcmd = unu["3op", "ifelse", "-w", "1", self.dwimask, "-", "0"] (slicecmd | maskcmd | gzipcmd) & FG else: (slicecmd | gzipcmd) & FG
def main(self): with TemporaryDirectory() as tmpdir, local.cwd(tmpdir): tmpdir = local.path(tmpdir) dicePrefix = 'dwi' logging.info("Dice DWI") (unu['convert', '-t', 'int16', '-i', self.dwi] | \ unu['dice','-a','3','-o',dicePrefix]) & FG logging.info("Apply warp to each DWI volume") vols = sorted(tmpdir // (dicePrefix + '*')) volsWarped = [] for vol in vols: if self.dwimask: unu('3op', 'ifelse', self.dwimask, vol, '0', '-o', vol) volwarped = vol.stem + '-warped.nrrd' WarpImageMultiTransform('3', vol, volwarped, '-R', vol, self.xfm) unu('convert', '-t', 'int16', '-i', volwarped, '-o', volwarped) volsWarped.append(volwarped) logging.info("Join warped volumes together") (unu['join', '-a', '3', '-i', volsWarped] | \ unu['save', '-e', 'gzip', '-f', 'nrrd'] | \ unu['data','-'] > 'tmpdwi.raw.gz') & FG logging.info( "Create new nrrd header pointing to the newly generated data file" ) unu('save', '-e', 'gzip', '-f', 'nrrd', '-i', self.dwi, '-o', 'dwi.nhdr') with open("dwi.nhdr", "r") as hdr: lines = hdr.readlines() with open("dwi.nhdr", "w") as hdr: for line in lines: hdr.write( re.sub(r'^data file:.*$', 'data file: tmpdwi.raw.gz', line)) logging.info('Make ' + str(self.out)) unu('save', '-e', 'gzip', '-f', 'nrrd', '-i', 'dwi.nhdr', '-o', self.out) logging.info('Made ' + str(self.out)) if self.debug: from os import getpid pid = str(getpid()) d = local.path(self.out.dirname / ('antsApplyTransformsDWi-' + pid)) tmpdir.copy(d)
def main(self): with TemporaryDirectory() as tmpdir, local.cwd(tmpdir): tmpdir = local.path(tmpdir) dicePrefix = 'dwi' logging.info("Dice DWI") unu['dice','-a','3','-i',self.dwi,'-o',dicePrefix] & FG logging.info("Apply warp to each DWI volume") vols = sorted(tmpdir // (dicePrefix + '*')) # use the following multi-processed loop pool= Pool(int(self.nproc)) res= [] for vol in vols: res.append(pool.apply_async(_WarpImage, (self.dwimask, vol, self.xfm))) volsWarped= [r.get() for r in res] pool.close() pool.join() # or use the following for loop # volsWarped = [] # for vol in vols: # if self.dwimask: # unu('3op','ifelse',self.dwimask,vol,'0','-o',vol) # volwarped = vol.stem + '-warped.nrrd' # WarpImageMultiTransform('3', vol, volwarped, '-R', vol, # self.xfm) # volsWarped.append(volwarped) # # logging.info("Join warped volumes together") (unu['join', '-a', '3', '-i', volsWarped] | \ unu['save', '-e', 'gzip', '-f', 'nrrd', '-o', 'dwi.nhdr']) & FG # get data type with open("dwi.nhdr", "r") as hdr: lines = hdr.readlines() for line in lines: if 'type' in line: typeline=line logging.info( "Create new nrrd header pointing to the newly generated data file") unu('save', '-e', 'gzip', '-f', 'nrrd', '-i', self.dwi, '-o', 'tmpdwi.nhdr') # get other header fields with open("tmpdwi.nhdr", "r") as hdr: lines = hdr.readlines() with open("dwi.nhdr", "w") as hdr: for line in lines: if 'data file' in line: hdr.write('data file: dwi.raw.gz\n') elif 'type' in line: hdr.write(typeline) else: hdr.write(line) logging.info('Make ' + str(self.out)) unu('save', '-e', 'gzip', '-f', 'nrrd', '-i', 'dwi.nhdr', '-o', self.out) logging.info('Made ' + str(self.out)) if self.debug: from os import getpid pid = str(getpid()) d = local.path(self.out.dirname / ('antsApplyTransformsDWi-' + pid)) tmpdir.copy(d)
def main(self): if not self.force and self.out.exists(): logging.error( "'{}' already exists, use '--force' to force overwrite.". format(self.out)) sys.exit(1) with TemporaryDirectory() as tmpdir: tmpdir = local.path(tmpdir) bse = tmpdir / "maskedbse.nrrd" t2masked = tmpdir / "maskedt2.nrrd" t2inbse = tmpdir / "t2inbse.nrrd" epiwarp = tmpdir / "epiwarp.nii.gz" t2tobse_rigid = tmpdir / "t2tobse_rigid" affine = tmpdir / "t2tobse_rigid0GenericAffine.mat" logging.info('1. Extract and mask the DWI b0') bse_py('-m', self.dwimask, '-i', self.dwi, '-o', bse) logging.info("2. Mask the T2") unu("3op", "ifelse", self.t2mask, self.t2, "0", "-o", t2masked) logging.info( "3. Compute a rigid registration from the T2 to the DWI baseline" ) antsRegistrationSyN_sh("-d", "3", "-f", bse, "-m", t2masked, "-t", "r", "-o", tmpdir / "t2tobse_rigid") antsApplyTransforms("-d", "3", "-i", t2masked, "-o", t2inbse, "-r", bse, "-t", affine) logging.info( "4. Compute 1d nonlinear registration from the DWI to the T2 along the phase direction" ) moving = bse fixed = t2inbse pre = tmpdir / "epi" dwiepi = tmpdir / ("dwiepi" + ''.join(self.out.suffixes)) antsRegistration("-d", "3", "-m", "cc[" + str(fixed) + "," + str(moving) + ",1,2]", "-t", "SyN[0.25,3,0]", "-c", "50x50x10", "-f", "4x2x1", "-s", "2x1x0", "--restrict-deformation", "0x1x0", "-v", "1", "-o", pre) local.path(str(pre) + "0Warp.nii.gz").move(epiwarp) logging.info("5. Apply warp to the DWI") antsApplyTransformsDWI_py['-i', self.dwi, '-m', self.dwimask, '-t', epiwarp, '-o', dwiepi, '-n', str(self.nproc)] & FG logging.info('6. Apply warp to the DWI mask') epimask = self.out.dirname / self.out.basename.split( '.')[0] + '-mask.nrrd' antsApplyTransforms('-d', '3', '-i', self.dwimask, '-o', epimask, '-n', 'NearestNeighbor', '-r', bse, '-t', epiwarp) unu('convert', '-t', 'uchar', '-i', epimask, '-o', epimask) if '.nhdr' in dwiepi.suffixes: unu("save", "-e", "gzip", "-f", "nrrd", "-i", dwiepi, "-o", self.out) else: dwiepi.move(self.out) # FIXME: the following conversion is only for UKFTractography, should be removed in future if self.typeCast: unu('convert', '-t', 'int16', '-i', self.out, '-o', self.out) if self.debug: tmpdir.copy(self.out.dirname / ("epidebug-" + str(getpid())))
def main(self): self.out = local.path(self.out) if self.out.exists(): if self.overwrite: self.out.delete() else: logging.error( "{} exists, use '--force' to overwrite it".format( self.out)) sys.exit(1) outxfms = self.out.dirname / self.out.stem + '-xfms.tgz' with TemporaryDirectory() as tmpdir, local.cwd(tmpdir): tmpdir = local.path(tmpdir) unu('save', '-f', 'nrrd', '-e', 'gzip', '-i', self.dwi, '-o', 'dwijoined.nhdr') logging.info('Dice the DWI') (unu['convert', '-t', 'int16', '-i', 'dwijoined.nhdr'] | unu['dice', '-a', '3', '-o', 'Diffusion-G'])() vols = tmpdir.glob('Diffusion-G*.nrrd') vols.sort() logging.info('Extract the B0') bse_py('-i', 'dwijoined.nhdr', '-o', 'b0.nrrd') ConvertBetweenFileFormats('b0.nrrd', 'b0.nii.gz', 'short') logging.info('Register each volume to the B0') volsRegistered = [] for vol in vols: volnii = vol.with_suffix('.nii.gz') ConvertBetweenFileFormats(vol, volnii, 'short') logging.info('Run FSL flirt affine registration') flirt('-interp', 'sinc', '-sincwidth', '7', '-sincwindow', 'blackman', '-in', volnii, '-ref', 'b0.nii.gz', '-nosearch', '-o', volnii, '-omat', volnii.with_suffix('.txt', depth=2), '-paddingsize', '1') volsRegistered.append(volnii) fslmerge('-t', 'EddyCorrect-DWI', volsRegistered) transforms = tmpdir.glob('Diffusion-G*.txt') transforms.sort() logging.info('Extract the rotations and realign the gradients') gDir = [] header = '' gNum = [] gframe = [] with open('dwijoined.nhdr') as f: for line in f: if line.find('DWMRI_gradient_') != -1: gNum.append(line[15:19]) gDir.append(map(float, line[21:-1].split())) elif line.find('data file:') != -1: header = header + 'data file: EddyCorrect-DWI.nii.gz\n' elif line.find('encoding:') != -1: header = header + line + 'byteskip: -1\n' elif line.find('measurement frame:') != -1: header = header + line mf = np.matrix([ map(float, line.split()[2][1:-1].split(',')), map(float, line.split()[3][1:-1].split(',')), map(float, line.split()[4][1:-1].split(',')) ]) elif line.find('space:') != -1: header = header + line # Here I assume either lps or ras so only need to check the first letter space = line.split()[1][0] if (space == 'l') | (space == 'L'): spctoras = np.matrix([[-1, 0, 0], [0, -1, 0], [0, 0, 1]]) else: spctoras = np.matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) else: header = header + line with open('EddyCorrect-DWI.nhdr', 'w') as f: f.write(header) i = 0 # Transforms are in RAS so need to do inv(MF)*inv(SPC2RAS)*ROTATION*SPC2RAS*MF*GRADIENT mfras = mf.I * spctoras.I rasmf = spctoras * mf for t in transforms: logging.info('Apply ' + t) tra = np.loadtxt(t) #removes the translation aff = np.matrix(tra[0:3, 0:3]) # computes the finite strain of aff to get the rotation rot = aff * aff.T # Computer the square root of rot [el, ev] = np.linalg.eig(rot) eL = np.identity(3) * np.sqrt(el) sq = ev * eL * ev.I # finally the rotation is defined as rot = sq.I * aff newdir = np.dot(mfras * rot * rasmf, gDir[i]) f.write('DWMRI_gradient_' + gNum[i] + ':= ' + str(newdir[0, 0]) + ' ' + str(newdir[0, 1]) + ' ' + str(newdir[0, 2]) + '\n') i = i + 1 tar('cvzf', outxfms, transforms) unu('save', '-f', 'nrrd', '-e', 'gzip', '-i', 'EddyCorrect-DWI.nhdr', '-o', self.out) if self.debug: tmpdir.move("eddy-debug-" + str(getpid()))