def computeJacard(aname, bname): ''' computeJacard('warpedDiff_IBSR_15_segTRI_fill_ana_IBSR_10_ana_strip.nii.gz', '/opt/registration/data/t1/IBSR18/IBSR_10/IBSR_10_segTRI_fill_ana.nii.gz' ) computeJacard('warpedDiff_IBSR_13_segTRI_fill_ana_IBSR_10_ana_strip.nii.gz', '/opt/registration/data/t1/IBSR18/IBSR_10/IBSR_10_segTRI_fill_ana.nii.gz' ) computeJacard('warpedAffine_IBSR_16_segTRI_fill_ana_IBSR_10_ana_strip.nii.gz', '/opt/registration/data/t1/IBSR18/IBSR_10/IBSR_10_segTRI_fill_ana.nii.gz') computeJacard('warpedAffine_IBSR_10_segTRI_fill_ana_IBSR_01_ana_strip.nii.gz', '/opt/registration/data/t1/IBSR18/IBSR_10/IBSR_10_seg_ana.nii.gz',None) computeJacard('warpedDiff_IBSR_01_segTRI_fill_ana_t1_icbm_normal_1mm_pn0_rf0_peeled.nii.gz', 'data/phantom_1.0mm_normal_crisp.rawb.nii.gz') ''' baseA=rcommon.getBaseFileName(aname) baseB=rcommon.getBaseFileName(bname) oname="jacard_"+baseA+"_"+baseB+".txt" if(os.path.exists(oname)): print 'Jacard overlap found. Skipped computation.' jacard=np.loadtxt(oname) return jacard nib_A=nib.load(aname) affineA=nib_A.get_affine() A=nib_A.get_data().squeeze().astype(np.int32) A=np.copy(A, order='C') print "A range:",A.min(), A.max() nib_B=nib.load(bname) newB=nib.Nifti1Image(nib_B.get_data(),affineA) newB.to_filename(bname) B=nib_B.get_data().squeeze().astype(np.int32) B=np.copy(B, order='C') print "B range:",B.min(), B.max() nlabels=1+np.max([A.max(), B.max()]) jacard=np.array(tf.compute_jacard(A,B, nlabels)) print "Jacard range:",jacard.min(), jacard.max() np.savetxt(oname,jacard) return jacard
def fullJacardAllPairs(names, segIndex, warpedPreffix): nlines=len(names) sumJacard=None sumJacard2=None minScore=None worstPair=None nsamples=0.0 for i in range(nlines): if not names[i]: continue registrationReference=names[i][0] reference=names[i][segIndex] for j in range(nlines): if i==j: continue if not names[j]: continue target=names[j][segIndex] ############### baseReference=rcommon.getBaseFileName(registrationReference) baseTarget=rcommon.getBaseFileName(target) warpedName=warpedPreffix+baseTarget+'_'+baseReference+'.nii.gz' jacard=computeJacard(reference, warpedName) nsamples+=1 if sumJacard==None: sumJacard=jacard sumJacard2=jacard**2 worstPair=(i,j) minScore=np.sum(jacard) else: lenOld=len(sumJacard) lenNew=len(jacard) extendedShape=(np.max([lenOld, lenNew]),) newSum=np.zeros(shape=extendedShape, dtype=np.float64) newSum2=np.zeros(shape=extendedShape, dtype=np.float64) newSum[:lenOld]=sumJacard[...] newSum[:lenNew]+=jacard[...] newSum2[:lenOld]=sumJacard2[...] newSum2[:lenNew]+=jacard[...]**2 sumJacard=newSum sumJacard2=newSum2 optSum=np.sum(jacard) if optSum<minScore: minScore=optSum worstPair=(i,j) meanJacard=sumJacard/nsamples variance=sumJacard2/nsamples-meanJacard**2#E[X^2] - E[X]^2 std=np.sqrt(variance) return meanJacard, std, worstPair, minScore
def warpANTSAffine(targetName, referenceName, affineName, oname, interpolationType='trilinear'): baseName=rcommon.getBaseFileName(targetName) nib_target=nib.load(targetName) nib_reference=nib.load(referenceName) M=nib_target.get_affine() F=nib_reference.get_affine() referenceShape=np.array(nib_reference.shape, dtype=np.int32) ######Load and compose affine##### if not affineName: T=np.eye(4) else: T=rcommon.readAntsAffine(affineName) affineComposition=np.linalg.inv(M).dot(T.dot(F)) ###################### if interpolationType=='NN': target=nib_target.get_data().squeeze().astype(np.int32) target=np.copy(target, order='C') warped=np.array(tf.warp_discrete_volumeNNAffine(target, referenceShape, affineComposition)).astype(np.int16) else: target=nib_target.get_data().squeeze().astype(np.float64) target=np.copy(target, order='C') warped=np.array(tf.warp_volume_affine(target, referenceShape, affineComposition)).astype(np.int16) warped=nib.Nifti1Image(warped, F) if not oname: oname="warped"+baseName+"nii.gz" warped.to_filename(oname)
def save_registration_results(init_affine, displacement, inverse, params): r''' Warp the target image using the obtained deformation field ''' fixed = nib.load(params.reference) fixed_affine = fixed.get_affine() reference_shape = np.array(fixed.shape, dtype=np.int32) warp_dir = params.warp_dir base_moving = rcommon.getBaseFileName(params.target) base_fixed = rcommon.getBaseFileName(params.reference) moving = nib.load(params.target).get_data().squeeze().astype(np.float64) moving = moving.copy(order='C') warped = np.array(tf.warp_volume(moving, displacement)).astype(np.int16) img_warped = nib.Nifti1Image(warped, fixed_affine) img_warped.to_filename('warpedDiff_'+base_moving+'_'+base_fixed+'.nii.gz') #---warp the target image using the affine transformation only--- moving = nib.load(params.target).get_data().squeeze().astype(np.float64) moving = moving.copy(order='C') warped = np.array( tf.warp_volume_affine(moving, reference_shape, init_affine) ).astype(np.int16) img_warped = nib.Nifti1Image(warped, fixed_affine) img_warped.to_filename('warpedAffine_'+base_moving+'_'+base_fixed+'.nii.gz') #---warp all volumes in the warp directory using NN interpolation names = [os.path.join(warp_dir, name) for name in os.listdir(warp_dir)] for name in names: to_warp = nib.load(name).get_data().squeeze().astype(np.int32) to_warp = to_warp.copy(order='C') base_warp = rcommon.getBaseFileName(name) warped = np.array( tf.warp_discrete_volumeNN(to_warp, displacement)).astype(np.int16) img_warped = nib.Nifti1Image(warped, fixed_affine) img_warped.to_filename('warpedDiff_'+base_warp+'_'+base_fixed+'.nii.gz') #---finally, the optional output if params.output_list == None: return if 'lattice' in params.output_list: save_deformed_lattice_3d( displacement, 'latticeDispDiff_'+base_moving+'_'+base_fixed+'.nii.gz') if 'inv_lattice' in params.output_list: save_deformed_lattice_3d( inverse, 'invLatticeDispDiff_'+base_moving+'_'+base_fixed+'.nii.gz') if 'displacement' in params.output_list: np.save('dispDiff_'+base_moving+'_'+base_fixed+'.npy', displacement) if 'inverse' in params.output_list: np.save('invDispDiff_'+base_moving+'_'+base_fixed+'.npy', inverse)
def changeExtension(fname, newExt): ''' changeExtension('/opt/registration/data/myfile.nii.gz', '.ext') changeExtension('/opt/registration/data/myfile.nii.gz', '_suffix.ext') ''' directory=os.path.dirname(fname) if directory: directory+='/' basename=rcommon.getBaseFileName(fname) return directory+basename+newExt
def warpNonlinear(targetName, referenceName, dispName, oname, interpolationType='trilinear'): baseName=rcommon.getBaseFileName(targetName) displacement=np.load(dispName) nib_target = nib.load(targetName) if interpolationType=='NN': target=nib_target.get_data().squeeze().astype(np.int32) target=np.copy(target, order='C') warped=np.array(tf.warp_discrete_volumeNN(target, displacement)) else: target=nib_target.get_data().squeeze().astype(np.float64) target=np.copy(target, order='C') warped=np.array(tf.warp_volume(target, displacement)) referenceAffine=nib.load(referenceName).get_affine() warped=nib.Nifti1Image(warped, referenceAffine) if not oname: oname="warped"+baseName+"nii.gz" warped.to_filename(oname)
def testEstimateMultimodalSyN3DMultiScale(fnameMoving, fnameFixed, fnameAffine, warpDir, lambdaParam): ''' testEstimateMultimodalDiffeomorphicField3DMultiScale('IBSR_01_ana_strip.nii.gz', 't1_icbm_normal_1mm_pn0_rf0_peeled.nii.gz', 'IBSR_01_ana_strip_t1_icbm_normal_1mm_pn0_rf0_peeledAffine.txt', 100) ''' print 'Registering', fnameMoving, 'to', fnameFixed, 'with lambda=', lambdaParam sys.stdout.flush() moving = nib.load(fnameMoving) fixed = nib.load(fnameFixed) referenceShape = np.array(fixed.shape, dtype=np.int32) M = moving.get_affine() F = fixed.get_affine() if not fnameAffine: T = np.eye(4) else: T = rcommon.readAntsAffine(fnameAffine) initAffine = np.linalg.inv(M).dot(T.dot(F)) print initAffine moving = moving.get_data().squeeze().astype(np.float64) fixed = fixed.get_data().squeeze().astype(np.float64) moving = np.copy(moving, order='C') fixed = np.copy(fixed, order='C') moving = (moving - moving.min()) / (moving.max() - moving.min()) fixed = (fixed - fixed.min()) / (fixed.max() - fixed.min()) level = 2 maskMoving = moving > 0 maskFixed = fixed > 0 movingPyramid = [ img for img in rcommon.pyramid_gaussian_3D(moving, level, maskMoving) ] fixedPyramid = [ img for img in rcommon.pyramid_gaussian_3D(fixed, level, maskFixed) ] #maxOuterIter=[25,50,100,100, 100, 100] maxOuterIter = [2, 2, 2, 2, 2, 2] baseMoving = rcommon.getBaseFileName(fnameMoving) baseFixed = rcommon.getBaseFileName(fnameFixed) # if(os.path.exists('disp_'+baseMoving+'_'+baseFixed+'.npy')): # displacement=np.load('disp_'+baseMoving+'_'+baseFixed+'.npy') # else: displacement, directInverse = estimateMultimodalSyN3DMultiScale( movingPyramid, fixedPyramid, initAffine, lambdaParam, maxOuterIter, 0) tf.prepend_affine_to_displacement_field(displacement, initAffine) # np.save('disp_'+baseMoving+'_'+baseFixed+'.npy', displacement) #####Warp all requested volumes #---first the target using tri-linear interpolation--- moving = nib.load(fnameMoving).get_data().squeeze().astype(np.float64) moving = np.copy(moving, order='C') warped = np.array(tf.warp_volume(moving, displacement)).astype(np.int16) imgWarped = nib.Nifti1Image(warped, F) imgWarped.to_filename('warpedDiff_' + baseMoving + '_' + baseFixed + '.nii.gz') #---warp using affine only moving = nib.load(fnameMoving).get_data().squeeze().astype(np.int32) moving = np.copy(moving, order='C') warped = np.array( tf.warp_discrete_volumeNNAffine(moving, referenceShape, initAffine)).astype(np.int16) imgWarped = nib.Nifti1Image( warped, F) #The affine transformation is the reference's one imgWarped.to_filename('warpedAffine_' + baseMoving + '_' + baseFixed + '.nii.gz') #---now the rest of the targets using nearest neighbor names = [os.path.join(warpDir, name) for name in os.listdir(warpDir)] for name in names: #---warp using the non-linear deformation toWarp = nib.load(name).get_data().squeeze().astype(np.int32) toWarp = np.copy(toWarp, order='C') baseWarp = rcommon.getBaseFileName(name) warped = np.array(tf.warp_discrete_volumeNN( toWarp, displacement)).astype(np.int16) imgWarped = nib.Nifti1Image( warped, F) #The affine transformation is the reference's one imgWarped.to_filename('warpedDiff_' + baseWarp + '_' + baseFixed + '.nii.gz') #---warp using affine inly warped = np.array( tf.warp_discrete_volumeNNAffine(toWarp, referenceShape, initAffine)).astype(np.int16) imgWarped = nib.Nifti1Image( warped, F) #The affine transformation is the reference's one imgWarped.to_filename('warpedAffine_' + baseWarp + '_' + baseFixed + '.nii.gz') #---finally, the deformed lattices (forward, inverse and resdidual)--- lambdaParam = 0.9 maxIter = 100 tolerance = 1e-4 print 'Computing inverse...' inverse = np.array( tf.invert_vector_field3D(displacement, lambdaParam, maxIter, tolerance)) residual = np.array(tf.compose_vector_fields3D(displacement, inverse)) saveDeformedLattice3D( displacement, 'latticeDispDiff_' + baseMoving + '_' + baseFixed + '.nii.gz') saveDeformedLattice3D( inverse, 'latticeInvDiff_' + baseMoving + '_' + baseFixed + '.nii.gz') saveDeformedLattice3D( residual, 'latticeResdiff_' + baseMoving + '_' + baseFixed + '.nii.gz') residual = np.sqrt(np.sum(residual**2, 3)) print "Mean residual norm:", residual.mean(), " (", residual.std( ), "). Max residual norm:", residual.max()
def testEstimateMultimodalSyN3DMultiScale(fnameMoving, fnameFixed, fnameAffine, warpDir, lambdaParam): ''' testEstimateMultimodalDiffeomorphicField3DMultiScale('IBSR_01_ana_strip.nii.gz', 't1_icbm_normal_1mm_pn0_rf0_peeled.nii.gz', 'IBSR_01_ana_strip_t1_icbm_normal_1mm_pn0_rf0_peeledAffine.txt', 100) ''' print 'Registering', fnameMoving, 'to', fnameFixed,'with lambda=',lambdaParam sys.stdout.flush() moving = nib.load(fnameMoving) fixed= nib.load(fnameFixed) referenceShape=np.array(fixed.shape, dtype=np.int32) M=moving.get_affine() F=fixed.get_affine() if not fnameAffine: T=np.eye(4) else: T=rcommon.readAntsAffine(fnameAffine) initAffine=np.linalg.inv(M).dot(T.dot(F)) print initAffine moving=moving.get_data().squeeze().astype(np.float64) fixed=fixed.get_data().squeeze().astype(np.float64) moving=np.copy(moving, order='C') fixed=np.copy(fixed, order='C') moving=(moving-moving.min())/(moving.max()-moving.min()) fixed=(fixed-fixed.min())/(fixed.max()-fixed.min()) level=2 maskMoving=moving>0 maskFixed=fixed>0 movingPyramid=[img for img in rcommon.pyramid_gaussian_3D(moving, level, maskMoving)] fixedPyramid=[img for img in rcommon.pyramid_gaussian_3D(fixed, level, maskFixed)] #maxOuterIter=[25,50,100,100, 100, 100] maxOuterIter=[2,2,2,2,2,2] baseMoving=rcommon.getBaseFileName(fnameMoving) baseFixed=rcommon.getBaseFileName(fnameFixed) # if(os.path.exists('disp_'+baseMoving+'_'+baseFixed+'.npy')): # displacement=np.load('disp_'+baseMoving+'_'+baseFixed+'.npy') # else: displacement, directInverse=estimateMultimodalSyN3DMultiScale(movingPyramid, fixedPyramid, initAffine, lambdaParam, maxOuterIter, 0) tf.prepend_affine_to_displacement_field(displacement, initAffine) # np.save('disp_'+baseMoving+'_'+baseFixed+'.npy', displacement) #####Warp all requested volumes #---first the target using tri-linear interpolation--- moving=nib.load(fnameMoving).get_data().squeeze().astype(np.float64) moving=np.copy(moving, order='C') warped=np.array(tf.warp_volume(moving, displacement)).astype(np.int16) imgWarped=nib.Nifti1Image(warped, F) imgWarped.to_filename('warpedDiff_'+baseMoving+'_'+baseFixed+'.nii.gz') #---warp using affine only moving=nib.load(fnameMoving).get_data().squeeze().astype(np.int32) moving=np.copy(moving, order='C') warped=np.array(tf.warp_discrete_volumeNNAffine(moving, referenceShape, initAffine)).astype(np.int16) imgWarped=nib.Nifti1Image(warped, F)#The affine transformation is the reference's one imgWarped.to_filename('warpedAffine_'+baseMoving+'_'+baseFixed+'.nii.gz') #---now the rest of the targets using nearest neighbor names=[os.path.join(warpDir,name) for name in os.listdir(warpDir)] for name in names: #---warp using the non-linear deformation toWarp=nib.load(name).get_data().squeeze().astype(np.int32) toWarp=np.copy(toWarp, order='C') baseWarp=rcommon.getBaseFileName(name) warped=np.array(tf.warp_discrete_volumeNN(toWarp, displacement)).astype(np.int16) imgWarped=nib.Nifti1Image(warped, F)#The affine transformation is the reference's one imgWarped.to_filename('warpedDiff_'+baseWarp+'_'+baseFixed+'.nii.gz') #---warp using affine inly warped=np.array(tf.warp_discrete_volumeNNAffine(toWarp, referenceShape, initAffine)).astype(np.int16) imgWarped=nib.Nifti1Image(warped, F)#The affine transformation is the reference's one imgWarped.to_filename('warpedAffine_'+baseWarp+'_'+baseFixed+'.nii.gz') #---finally, the deformed lattices (forward, inverse and resdidual)--- lambdaParam=0.9 maxIter=100 tolerance=1e-4 print 'Computing inverse...' inverse=np.array(tf.invert_vector_field3D(displacement, lambdaParam, maxIter, tolerance)) residual=np.array(tf.compose_vector_fields3D(displacement, inverse)) saveDeformedLattice3D(displacement, 'latticeDispDiff_'+baseMoving+'_'+baseFixed+'.nii.gz') saveDeformedLattice3D(inverse, 'latticeInvDiff_'+baseMoving+'_'+baseFixed+'.nii.gz') saveDeformedLattice3D(residual, 'latticeResdiff_'+baseMoving+'_'+baseFixed+'.nii.gz') residual=np.sqrt(np.sum(residual**2,3)) print "Mean residual norm:", residual.mean()," (",residual.std(), "). Max residual norm:", residual.max()
parser.add_argument('--similarity', action='store', metavar='String', help="Cost-function for assessing image similarity. If a string, one of 'cc': correlation coefficient, 'cr': correlation ratio, 'crl1': L1-norm based correlation ratio, 'mi': mutual information, 'nmi': normalized mutual information, 'slr': supervised log-likelihood ratio. If a callable, it should take a two-dimensional array representing the image joint histogram as an input and return a float.", default='crl1') parser.add_argument('--interp', action='store', metavar='String', help="'Interpolation method.One of 'pv': Partial volume, 'tri':Trilinear, 'rand': Random interpolation'", default='pv') params = parser.parse_args() if __name__ == '__main__': fmoving = params.in_file fstatic = params.reference baseFixed=baseFixed=rcommon.getBaseFileName(fstatic) print(fmoving + ' --> ' + fstatic) static=nib.load(fstatic) static=nib.Nifti1Image(static.get_data().squeeze(), static.get_affine()) static = nifti2nipy(static) moving=nib.load(fmoving) moving=nib.Nifti1Image(moving.get_data().squeeze(), moving.get_affine()) moving= nifti2nipy(moving) similarity = params.similarity #'crl1' 'cc', 'mi', 'nmi', 'cr', 'slr' interp = params.interp #'pv', 'tri', renormalize = True optimizer = 'powell' print('Setting up registration...')
default='crl1') parser.add_argument( '--interp', action='store', metavar='String', help= "'Interpolation method.One of 'pv': Partial volume, 'tri':Trilinear, 'rand': Random interpolation'", default='pv') params = parser.parse_args() if __name__ == '__main__': fmoving = params.in_file fstatic = params.reference baseFixed = baseFixed = rcommon.getBaseFileName(fstatic) print(fmoving + ' --> ' + fstatic) static = nib.load(fstatic) static = nib.Nifti1Image(static.get_data().squeeze(), static.get_affine()) static = nifti2nipy(static) moving = nib.load(fmoving) moving = nib.Nifti1Image(moving.get_data().squeeze(), moving.get_affine()) moving = nifti2nipy(moving) similarity = params.similarity #'crl1' 'cc', 'mi', 'nmi', 'cr', 'slr' interp = params.interp #'pv', 'tri', renormalize = True optimizer = 'powell' print('Setting up registration...')