Exemplo n.º 1
0
 def update(new_displacement, current_displacement):
     dim = len(new_displacement.shape)-1
     mse = np.sqrt(np.sum((current_displacement**2), -1)).mean()
     if dim == 2:
         updated, stats = tf.compose_vector_fields(new_displacement, 
                                                   current_displacement)
     else:
         updated, stats = tf.compose_vector_fields3D(new_displacement, 
                                                     current_displacement)
     return np.array(updated), np.array(mse)
def estimateNewMonomodalDiffeomorphicField3D(moving,
                                             fixed,
                                             lambdaParam,
                                             maxOuterIter,
                                             previousDisplacement,
                                             reportProgress=False):
    '''
    Warning: in the monomodal case, the parameter lambda must be significantly lower than in the multimodal case. Try lambdaParam=1,
    as opposed as lambdaParam=150 used in the multimodal case
    '''
    innerTolerance = 1e-3
    outerTolerance = 1e-3
    displacement = np.zeros(shape=(moving.shape) + (3, ), dtype=np.float64)
    residuals = np.zeros(shape=(moving.shape), dtype=np.float64)
    gradientField = np.empty(shape=(moving.shape) + (3, ), dtype=np.float64)
    totalDisplacement = np.zeros(shape=(moving.shape) + (3, ),
                                 dtype=np.float64)
    if (previousDisplacement != None):
        totalDisplacement[...] = previousDisplacement
    outerIter = 0
    while (outerIter < maxOuterIter):
        outerIter += 1
        if (reportProgress):
            print 'Iter:', outerIter, '/', maxOuterIter
        warped = np.array(tf.warp_volume(moving, totalDisplacement))
        sigmaField = np.ones_like(warped, dtype=np.float64)
        deltaField = fixed - warped
        g0, g1, g2 = sp.gradient(warped)
        gradientField[:, :, :, 0] = g0
        gradientField[:, :, :, 1] = g1
        gradientField[:, :, :, 2] = g2
        maxVariation = 1 + innerTolerance
        innerIter = 0
        maxResidual = 0
        displacement[...] = 0
        maxInnerIter = 50
        while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)):
            innerIter += 1
            maxVariation = tf.iterateDisplacementField3DCYTHON(
                deltaField, sigmaField, gradientField, lambdaParam,
                totalDisplacement, displacement, residuals)
            opt = np.max(residuals)
            if (maxResidual < opt):
                maxResidual = opt
        maxDisplacement = np.max(np.abs(displacement))
        totalDisplacement, stats = tf.compose_vector_fields3D(
            displacement, totalDisplacement)
        if (maxDisplacement < outerTolerance):
            break
    print "Iter: ", outerIter, "Max lateral displacement:", maxDisplacement, "Max variation:", maxVariation, "Max residual:", maxResidual
    if (previousDisplacement != None):
        return totalDisplacement - previousDisplacement
    return totalDisplacement
Exemplo n.º 3
0
def estimateMultimodalSyN3DMultiScale(movingPyramid,
                                      fixedPyramid,
                                      initAffine,
                                      lambdaParam,
                                      maxOuterIter,
                                      level=0):
    n = len(movingPyramid)
    quantizationLevels = 256
    if (level == (n - 1)):
        totalF, totalFInv, totalM, totalMInv = estimateNewMultimodalSyNField3D(
            movingPyramid[level], fixedPyramid[level], None, None, None, None,
            initAffine, lambdaParam, quantizationLevels, maxOuterIter[level],
            level == 0)
        return totalF, totalFInv, totalM, totalMInv
    subAffine = initAffine.copy()
    subAffine[:3, 3] *= 0.5
    subF, subFInv, subM, subMInv = estimateMultimodalSyN3DMultiScale(
        movingPyramid, fixedPyramid, subAffine, lambdaParam, maxOuterIter,
        level + 1)
    sh = np.array(fixedPyramid[level].shape).astype(np.int32)
    upF = np.array(tf.upsample_displacement_field3D(subF, sh)) * 2
    upFInv = np.array(tf.upsample_displacement_field3D(subFInv, sh)) * 2
    upM = np.array(tf.upsample_displacement_field3D(subM, sh)) * 2
    upMInv = np.array(tf.upsample_displacement_field3D(subMInv, sh)) * 2
    del subF
    del subFInv
    del subM
    del subMInv
    totalF, totalFInv, totalM, totalMInv = estimateNewMultimodalSyNField3D(
        movingPyramid[level], fixedPyramid[level], upF, upFInv, upM, upMInv,
        initAffine, lambdaParam, quantizationLevels, maxOuterIter[level],
        level == 0)
    if level == 0:
        totalF = np.array(tf.compose_vector_fields3D(
            totalF, totalMInv))  #Multiply bw by 0.5??
        totalM = np.array(tf.compose_vector_fields3D(
            totalM, totalFInv))  #Multiply bw by 0.5??
        return totalM, totalF
    return totalF, totalFInv, totalM, totalMInv
Exemplo n.º 4
0
 def compute_inversion_error(self):
     r'''
     Returns the inversion error of the displacement fields
     TO-DO: the inversion error should take into account the affine
     transformations as well.
     '''
     if self.dim == 2:
         residual, stats = tf.compose_vector_fields(self.forward,
                                                    self.backward)
     else:
         residual, stats = tf.compose_vector_fields3D(self.forward,
                                                      self.backward)
     return residual, stats
Exemplo n.º 5
0
 def compose(self, applyFirst):
     r'''
     Computes the composition G(F(.)) where G is this transformation and
     F is the transformation given as parameter
     '''
     B=applyFirst.affine_post
     C=self.affine_pre
     if B==None:
         affine_prod=C
     elif C==None:
         affine_prod=B
     else:
         affine_prod=C.dot(B)
     if affine_prod!=None:
         affine_prod_inv=linalg.inv(affine_prod).copy(order='C')
     else:
         affine_prod_inv=None
     if self.dim == 2:
         forward=applyFirst.forward.copy()
         tf.append_affine_to_displacement_field_2d(forward, affine_prod)
         forward, stats = tf.compose_vector_fields(forward,
                                                   self.forward)
         backward=self.backward.copy()
         tf.append_affine_to_displacement_field_2d(backward, affine_prod_inv)
         backward, stats = tf.compose_vector_fields(backward, 
                                                    applyFirst.backward)
     else:
         forward=applyFirst.forward.copy()
         tf.append_affine_to_displacement_field_3d(forward, affine_prod)
         forward, stats = tf.compose_vector_fields3D(forward,
                                                   self.forward)
         backward=self.backward.copy()
         tf.append_affine_to_displacement_field_3d(backward, affine_prod_inv)
         backward, stats = tf.compose_vector_fields3D(backward, 
                                                    applyFirst.backward)
     composition=TransformationModel(forward, backward, 
                                     applyFirst.affine_pre, self.affine_post)
     return composition
Exemplo n.º 6
0
def estimateMultimodalSyN3DMultiScale(movingPyramid, fixedPyramid, initAffine, lambdaParam, maxOuterIter, level=0):
    n=len(movingPyramid)
    quantizationLevels=256
    if(level==(n-1)):
        totalF, totalFInv, totalM, totalMInv=estimateNewMultimodalSyNField3D(movingPyramid[level], fixedPyramid[level], None, None, None, None, initAffine, lambdaParam, quantizationLevels, maxOuterIter[level], level==0)
        return totalF, totalFInv, totalM, totalMInv
    subAffine=initAffine.copy()
    subAffine[:3,3]*=0.5
    subF, subFInv, subM, subMInv=estimateMultimodalSyN3DMultiScale(movingPyramid, fixedPyramid, subAffine, lambdaParam, maxOuterIter, level+1)
    sh=np.array(fixedPyramid[level].shape).astype(np.int32)
    upF=np.array(tf.upsample_displacement_field3D(subF, sh))*2
    upFInv=np.array(tf.upsample_displacement_field3D(subFInv, sh))*2
    upM=np.array(tf.upsample_displacement_field3D(subM, sh))*2
    upMInv=np.array(tf.upsample_displacement_field3D(subMInv, sh))*2
    del subF
    del subFInv
    del subM
    del subMInv
    totalF, totalFInv, totalM, totalMInv=estimateNewMultimodalSyNField3D(movingPyramid[level], fixedPyramid[level], upF, upFInv, upM, upMInv, initAffine, lambdaParam, quantizationLevels, maxOuterIter[level], level==0)
    if level==0:
        totalF=np.array(tf.compose_vector_fields3D(totalF, totalMInv))#Multiply bw by 0.5??
        totalM=np.array(tf.compose_vector_fields3D(totalM, totalFInv))#Multiply bw by 0.5??
        return totalM, totalF
    return totalF, totalFInv, totalM, totalMInv
def estimateNewMonomodalDiffeomorphicField3D(moving, fixed, lambdaParam, maxOuterIter, previousDisplacement, reportProgress=False):
    '''
    Warning: in the monomodal case, the parameter lambda must be significantly lower than in the multimodal case. Try lambdaParam=1,
    as opposed as lambdaParam=150 used in the multimodal case
    '''
    innerTolerance=1e-3
    outerTolerance=1e-3
    displacement     =np.zeros(shape=(moving.shape)+(3,), dtype=np.float64)
    residuals=np.zeros(shape=(moving.shape), dtype=np.float64)
    gradientField    =np.empty(shape=(moving.shape)+(3,), dtype=np.float64)
    totalDisplacement=np.zeros(shape=(moving.shape)+(3,), dtype=np.float64)
    if(previousDisplacement!=None):
        totalDisplacement[...]=previousDisplacement
    outerIter=0
    while(outerIter<maxOuterIter):
        outerIter+=1
        if(reportProgress):
            print 'Iter:',outerIter,'/',maxOuterIter
        warped=np.array(tf.warp_volume(moving, totalDisplacement))
        sigmaField=np.ones_like(warped, dtype=np.float64)
        deltaField=fixed-warped
        g0, g1, g2=sp.gradient(warped)
        gradientField[:,:,:,0]=g0
        gradientField[:,:,:,1]=g1
        gradientField[:,:,:,2]=g2
        maxVariation=1+innerTolerance
        innerIter=0
        maxResidual=0
        displacement[...]=0
        maxInnerIter=50
        while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)):
            innerIter+=1
            maxVariation=tf.iterateDisplacementField3DCYTHON(deltaField, sigmaField, gradientField,  lambdaParam, totalDisplacement, displacement, residuals)
            opt=np.max(residuals)
            if(maxResidual<opt):
                maxResidual=opt
        maxDisplacement=np.max(np.abs(displacement))
        totalDisplacement, stats=tf.compose_vector_fields3D(displacement, totalDisplacement)
        if(maxDisplacement<outerTolerance):
            break
    print "Iter: ",outerIter, "Max lateral displacement:", maxDisplacement, "Max variation:",maxVariation, "Max residual:", maxResidual
    if(previousDisplacement!=None):
        return totalDisplacement-previousDisplacement
    return totalDisplacement
Exemplo n.º 8
0
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()
Exemplo n.º 9
0
def estimateNewMultimodalSyNField3D(moving,
                                    fixed,
                                    fWarp,
                                    fInv,
                                    mWarp,
                                    mInv,
                                    initAffine,
                                    lambdaDisplacement,
                                    quantizationLevels,
                                    maxOuterIter,
                                    reportProgress=False):
    '''
        fwWarp: forward warp, the displacement field that warps moving towards fixed
        bwWarp: backward warp, the displacement field that warps fixed towards moving
        initAffine: the affine transformation to bring moving over fixed (this part is not symmetric)
    '''
    print 'Moving shape:', moving.shape, '. Fixed shape:', fixed.shape
    innerTolerance = 1e-3
    outerTolerance = 1e-3
    fixedMask = (fixed > 0).astype(np.int32)
    movingMask = (moving > 0).astype(np.int32)
    if (fWarp != None):
        totalF = fWarp
        totalFInv = fInv
    else:
        totalF = np.zeros(shape=(fixed.shape) + (3, ), dtype=np.float64)
        totalFInv = np.zeros(shape=(fixed.shape) + (3, ), dtype=np.float64)
    if (mWarp != None):
        totalM = mWarp
        totalMInv = mInv
    else:
        totalM = np.zeros(shape=(moving.shape) + (3, ), dtype=np.float64)
        totalMInv = np.zeros(shape=(moving.shape) + (3, ), dtype=np.float64)
    finished = False
    outerIter = 0
    while ((not finished) and (outerIter < maxOuterIter)):
        outerIter += 1
        if (reportProgress):
            print 'Iter:', outerIter, '/', maxOuterIter
        #---E step---
        wmoving = np.array(tf.warp_volume(moving, totalMInv, initAffine))
        wmovingMask = np.array(
            tf.warp_discrete_volumeNN(movingMask, totalMInv,
                                      initAffine)).astype(np.int32)
        wfixed = np.array(tf.warp_volume(fixed, totalFInv))
        wfixedMask = np.array(tf.warp_discrete_volumeNN(
            fixedMask, totalFInv)).astype(np.int32)
        fixedQ, grayLevels, hist = tf.quantizePositiveVolumeCYTHON(
            wfixed, quantizationLevels)
        fixedQ = np.array(fixedQ, dtype=np.int32)
        movingQ, grayLevels, hist = tf.quantizePositiveVolumeCYTHON(
            wmoving, quantizationLevels)
        movingQ = np.array(movingQ, dtype=np.int32)
        trust = wfixedMask * wmovingMask
        meansMoving, variancesMoving = tf.computeMaskedVolumeClassStatsCYTHON(
            trust, wmoving, quantizationLevels, fixedQ)
        meansFixed, variancesFixed = tf.computeMaskedVolumeClassStatsCYTHON(
            trust, wfixed, quantizationLevels, movingQ)
        meansMoving[0] = 0
        meansFixed[0] = 0
        meansMoving = np.array(meansMoving)
        meansFixed = np.array(meansFixed)
        variancesMoving = np.array(variancesMoving)
        sigmaFieldMoving = variancesMoving[fixedQ]
        variancesFixed = np.array(variancesFixed)
        sigmaFieldFixed = variancesFixed[movingQ]
        deltaFieldMoving = meansMoving[fixedQ] - wmoving
        deltaFieldFixed = meansFixed[movingQ] - wfixed
        #--M step--
        movingGradient = np.empty(shape=(moving.shape) + (3, ),
                                  dtype=np.float64)
        movingGradient[:, :, :,
                       0], movingGradient[:, :, :,
                                          1], movingGradient[:, :, :,
                                                             2] = sp.gradient(
                                                                 wmoving)
        #iterate forward field
        maxVariation = 1 + innerTolerance
        innerIter = 0
        maxInnerIter = 100
        fw = np.zeros_like(totalF)
        while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)):
            innerIter += 1
            maxVariation = tf.iterateDisplacementField3DCYTHON(
                deltaFieldMoving, sigmaFieldMoving, movingGradient,
                lambdaDisplacement, totalF, fw, None)
        del movingGradient
        fw *= 0.5
        totalF = np.array(tf.compose_vector_fields3D(
            fw, totalF))  #Multiply fw by 0.5??
        nrm = np.sqrt(fw[..., 0]**2 + fw[..., 1]**2 + fw[..., 2]**2)
        del fw
        #iterate backward field
        fixedGradient = np.empty(shape=(fixed.shape) + (3, ), dtype=np.float64)
        fixedGradient[:, :, :,
                      0], fixedGradient[:, :, :,
                                        1], fixedGradient[:, :, :,
                                                          2] = sp.gradient(
                                                              wfixed)
        maxVariation = 1 + innerTolerance
        innerIter = 0
        maxInnerIter = 100
        mw = np.zeros_like(totalM)
        while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)):
            innerIter += 1
            maxVariation = tf.iterateDisplacementField3DCYTHON(
                deltaFieldFixed, sigmaFieldFixed, fixedGradient,
                lambdaDisplacement, totalM, mw, None)
        del fixedGradient
        mw *= 0.5
        totalM = np.array(tf.compose_vector_fields3D(
            mw, totalM))  #Multiply bw by 0.5??
        nrm = np.sqrt(mw[..., 0]**2 + mw[..., 1]**2 + mw[..., 2]**2)
        del mw
        #invert fields
        totalFInv = np.array(
            tf.invert_vector_field_fixed_point3D(totalF, 20, 1e-6))
        totalMInv = np.array(
            tf.invert_vector_field_fixed_point3D(totalM, 20, 1e-6))
        totalF = np.array(
            tf.invert_vector_field_fixed_point3D(totalFInv, 20, 1e-6))
        totalM = np.array(
            tf.invert_vector_field_fixed_point3D(totalMInv, 20, 1e-6))
        maxDisplacement = np.mean(nrm)
        if ((maxDisplacement < outerTolerance) or (outerIter >= maxOuterIter)):
            finished = True
    print "Iter: ", outerIter, "Mean displacement:", maxDisplacement, "Max variation:", maxVariation
    return totalF, totalFInv, totalM, totalMInv
Exemplo n.º 10
0
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()
Exemplo n.º 11
0
def estimateNewMultimodalSyNField3D(moving, fixed, fWarp, fInv, mWarp, mInv, initAffine, lambdaDisplacement, quantizationLevels, maxOuterIter, reportProgress=False):
    '''
        fwWarp: forward warp, the displacement field that warps moving towards fixed
        bwWarp: backward warp, the displacement field that warps fixed towards moving
        initAffine: the affine transformation to bring moving over fixed (this part is not symmetric)
    '''
    print 'Moving shape:',moving.shape,'. Fixed shape:',fixed.shape
    innerTolerance=1e-3
    outerTolerance=1e-3
    fixedMask=(fixed>0).astype(np.int32)
    movingMask=(moving>0).astype(np.int32)
    if(fWarp!=None):
        totalF=fWarp
        totalFInv=fInv
    else:
        totalF    =np.zeros(shape=(fixed.shape)+(3,), dtype=np.float64)
        totalFInv =np.zeros(shape=(fixed.shape)+(3,), dtype=np.float64)
    if(mWarp!=None):
        totalM=mWarp
        totalMInv=mInv
    else:
        totalM   =np.zeros(shape=(moving.shape)+(3,), dtype=np.float64)
        totalMInv=np.zeros(shape=(moving.shape)+(3,), dtype=np.float64)
    finished=False
    outerIter=0
    while((not finished) and (outerIter<maxOuterIter)):
        outerIter+=1
        if(reportProgress):
            print 'Iter:',outerIter,'/',maxOuterIter
        #---E step---
        wmoving=np.array(tf.warp_volume(moving, totalMInv, initAffine))
        wmovingMask=np.array(tf.warp_discrete_volumeNN(movingMask, totalMInv, initAffine)).astype(np.int32)
        wfixed=np.array(tf.warp_volume(fixed, totalFInv))
        wfixedMask=np.array(tf.warp_discrete_volumeNN(fixedMask, totalFInv)).astype(np.int32)
        fixedQ, grayLevels, hist=tf.quantizePositiveVolumeCYTHON(wfixed, quantizationLevels)
        fixedQ=np.array(fixedQ, dtype=np.int32)
        movingQ, grayLevels, hist=tf.quantizePositiveVolumeCYTHON(wmoving, quantizationLevels)
        movingQ=np.array(movingQ, dtype=np.int32)
        trust=wfixedMask*wmovingMask
        meansMoving, variancesMoving=tf.computeMaskedVolumeClassStatsCYTHON(trust, wmoving, quantizationLevels, fixedQ)
        meansFixed, variancesFixed=tf.computeMaskedVolumeClassStatsCYTHON(trust, wfixed, quantizationLevels, movingQ)
        meansMoving[0]=0
        meansFixed[0]=0
        meansMoving=np.array(meansMoving)
        meansFixed=np.array(meansFixed)
        variancesMoving=np.array(variancesMoving)
        sigmaFieldMoving=variancesMoving[fixedQ]
        variancesFixed=np.array(variancesFixed)
        sigmaFieldFixed=variancesFixed[movingQ]
        deltaFieldMoving=meansMoving[fixedQ]-wmoving
        deltaFieldFixed=meansFixed[movingQ]-wfixed
        #--M step--
        movingGradient  =np.empty(shape=(moving.shape)+(3,), dtype=np.float64)
        movingGradient[:,:,:,0], movingGradient[:,:,:,1], movingGradient[:,:,:,2]=sp.gradient(wmoving)
        #iterate forward field
        maxVariation=1+innerTolerance
        innerIter=0
        maxInnerIter=100
        fw=np.zeros_like(totalF)
        while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)):
            innerIter+=1
            maxVariation=tf.iterateDisplacementField3DCYTHON(deltaFieldMoving, sigmaFieldMoving, movingGradient,  lambdaDisplacement, totalF, fw, None)
        del movingGradient
        fw*=0.5
        totalF=np.array(tf.compose_vector_fields3D(fw, totalF))#Multiply fw by 0.5??
        nrm=np.sqrt(fw[...,0]**2+fw[...,1]**2+fw[...,2]**2)
        del fw        
        #iterate backward field
        fixedGradient   =np.empty(shape=(fixed.shape)+(3,), dtype=np.float64)
        fixedGradient[:,:,:,0], fixedGradient[:,:,:,1], fixedGradient[:,:,:,2]=sp.gradient(wfixed)
        maxVariation=1+innerTolerance
        innerIter=0
        maxInnerIter=100
        mw=np.zeros_like(totalM)
        while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)):
            innerIter+=1
            maxVariation=tf.iterateDisplacementField3DCYTHON(deltaFieldFixed, sigmaFieldFixed, fixedGradient,  lambdaDisplacement, totalM, mw, None)
        del fixedGradient
        mw*=0.5
        totalM=np.array(tf.compose_vector_fields3D(mw, totalM))#Multiply bw by 0.5??
        nrm=np.sqrt(mw[...,0]**2+mw[...,1]**2+mw[...,2]**2)
        del mw        
        #invert fields
        totalFInv=np.array(tf.invert_vector_field_fixed_point3D(totalF, 20, 1e-6))
        totalMInv=np.array(tf.invert_vector_field_fixed_point3D(totalM, 20, 1e-6))
        totalF=np.array(tf.invert_vector_field_fixed_point3D(totalFInv, 20, 1e-6))
        totalM=np.array(tf.invert_vector_field_fixed_point3D(totalMInv, 20, 1e-6))
        maxDisplacement=np.mean(nrm)
        if((maxDisplacement<outerTolerance)or(outerIter>=maxOuterIter)):
            finished=True
    print "Iter: ",outerIter, "Mean displacement:", maxDisplacement, "Max variation:",maxVariation
    return totalF, totalFInv, totalM, totalMInv
Exemplo n.º 12
0
def estimateNewMultimodalDiffeomorphicField3D(moving,
                                              fixed,
                                              initAffine,
                                              lambdaDisplacement,
                                              quantizationLevels,
                                              maxOuterIter,
                                              previousDisplacement,
                                              reportProgress=False):
    innerTolerance = 1e-3
    outerTolerance = 1e-3
    displacement = np.empty(shape=(fixed.shape) + (3, ), dtype=np.float64)
    residuals = np.zeros(shape=(fixed.shape), dtype=np.float64)
    gradientField = np.empty(shape=(fixed.shape) + (3, ), dtype=np.float64)
    totalDisplacement = np.zeros(shape=(fixed.shape) + (3, ), dtype=np.float64)
    if (previousDisplacement != None):
        totalDisplacement[...] = previousDisplacement
    fixedQ = None
    grayLevels = None
    fixedQ, grayLevels, hist = tf.quantizePositiveVolumeCYTHON(
        fixed, quantizationLevels)
    fixedQ = np.array(fixedQ, dtype=np.int32)
    finished = False
    outerIter = 0
    maxDisplacement = None
    maxVariation = None
    maxResidual = 0
    fixedMask = (fixed > 0).astype(np.int32)
    movingMask = (moving > 0).astype(np.int32)
    trustRegion = fixedMask * np.array(
        tf.warp_discrete_volumeNNAffine(
            movingMask, np.array(fixedMask.shape, dtype=np.int32),
            initAffine))  #consider only the overlap after affine registration
    while ((not finished) and (outerIter < maxOuterIter)):
        outerIter += 1
        if (reportProgress):
            print 'Iter:', outerIter, '/', maxOuterIter
            #sys.stdout.flush()
        #---E step---
        #print "Warping..."
        #sys.stdout.flush()
        warped = np.array(tf.warp_volume(moving, totalDisplacement,
                                         initAffine))
        warpedMask = np.array(
            tf.warp_discrete_volumeNN(
                trustRegion, totalDisplacement, np.eye(4))).astype(
                    np.int32)  #the affine mapping was already applied
        #print "Warping NN..."
        #sys.stdout.flush()
        #warpedMovingMask=np.array(tf.warp_volumeNN(movingMask, totalDisplacement)).astype(np.int32)
        #print "Class stats..."
        #sys.stdout.flush()
        means, variances = tf.computeMaskedVolumeClassStatsCYTHON(
            warpedMask, warped, quantizationLevels, fixedQ)
        means[0] = 0
        means = np.array(means)
        variances = np.array(variances)
        sigmaField = variances[fixedQ]
        deltaField = means[
            fixedQ] - warped  #########Delta-field using Arce's rule
        #--M step--
        g0, g1, g2 = sp.gradient(warped)
        gradientField[:, :, :, 0] = g0
        gradientField[:, :, :, 1] = g1
        gradientField[:, :, :, 2] = g2
        maxVariation = 1 + innerTolerance
        innerIter = 0
        maxInnerIter = 100
        displacement[...] = 0
        #print "Iterating..."
        #sys.stdout.flush()
        while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)):
            innerIter += 1
            maxVariation = tf.iterateDisplacementField3DCYTHON(
                deltaField, sigmaField, gradientField, lambdaDisplacement,
                totalDisplacement, displacement, residuals)
            opt = np.max(residuals)
            if (maxResidual < opt):
                maxResidual = opt
        #--accumulate displacement--
        #print "Exponential3D. Range D:", displacement.min(), displacement.max()
        #sys.stdout.flush()
        expd, inverseNone = tf.vector_field_exponential3D(displacement, False)
        expd = np.array(expd)
        #print "Range expd:", expd.min(), expd.max(), "Range TD:", totalDisplacement.min(), totalDisplacement.max()
        #print "Compose vector fields..."
        #sys.stdout.flush()
        totalDisplacement, stats = tf.compose_vector_fields3D(
            expd, totalDisplacement)
        totalDisplacement = np.array(totalDisplacement)
        #print "Composed rage:", totalDisplacement.min(), totalDisplacement.max()
        #sys.stdout.flush()
        #--check stop condition--
        nrm = np.sqrt(displacement[..., 0]**2 + displacement[..., 1]**2 +
                      displacement[..., 2]**2)
        #maxDisplacement=np.max(nrm)
        maxDisplacement = np.mean(nrm)
        if ((maxDisplacement < outerTolerance) or (outerIter >= maxOuterIter)):
            finished = True
    print "Iter: ", outerIter, "Mean displacement:", maxDisplacement, "Max variation:", maxVariation, "Max residual:", maxResidual
    #sh=fixed.shape
    #rcommon.overlayImages(warped[:,sh[1]//2,:], fixed[:,sh[1]//2,:])
    #rcommon.overlayImages(warped[:,sh[1]//2,:]*warpedMask[:,sh[1]//2,:], fixed[:,sh[1]//2,:])
    #sys.stdout.flush()
    if (previousDisplacement != None):
        #print 'Range TD:', totalDisplacement.min(), totalDisplacement.max(),'. Range PD:', previousDisplacement.min(), previousDisplacement.max()
        #sys.stdout.flush()
        return totalDisplacement - previousDisplacement
    return totalDisplacement
def estimateNewMultimodalDiffeomorphicField3D(moving, fixed, initAffine, lambdaDisplacement, quantizationLevels, maxOuterIter, previousDisplacement, reportProgress=False):
    innerTolerance=1e-3
    outerTolerance=1e-3
    displacement     =np.empty(shape=(fixed.shape)+(3,), dtype=np.float64)
    residuals=np.zeros(shape=(fixed.shape), dtype=np.float64)
    gradientField    =np.empty(shape=(fixed.shape)+(3,), dtype=np.float64)
    totalDisplacement=np.zeros(shape=(fixed.shape)+(3,), dtype=np.float64)
    if(previousDisplacement!=None):
        totalDisplacement[...]=previousDisplacement
    fixedQ=None
    grayLevels=None
    fixedQ, grayLevels, hist=tf.quantizePositiveVolumeCYTHON(fixed, quantizationLevels)
    fixedQ=np.array(fixedQ, dtype=np.int32)
    finished=False
    outerIter=0
    maxDisplacement=None
    maxVariation=None
    maxResidual=0
    fixedMask=(fixed>0).astype(np.int32)
    movingMask=(moving>0).astype(np.int32)
    trustRegion=fixedMask*np.array(tf.warp_discrete_volumeNNAffine(movingMask, np.array(fixedMask.shape, dtype=np.int32), initAffine))#consider only the overlap after affine registration
    while((not finished) and (outerIter<maxOuterIter)):
        outerIter+=1
        if(reportProgress):
            print 'Iter:',outerIter,'/',maxOuterIter
            #sys.stdout.flush()
        #---E step---
        #print "Warping..."
        #sys.stdout.flush()
        warped=np.array(tf.warp_volume(moving, totalDisplacement, initAffine))
        warpedMask=np.array(tf.warp_discrete_volumeNN(trustRegion, totalDisplacement, np.eye(4))).astype(np.int32)#the affine mapping was already applied
        #print "Warping NN..."
        #sys.stdout.flush()
        #warpedMovingMask=np.array(tf.warp_volumeNN(movingMask, totalDisplacement)).astype(np.int32)
        #print "Class stats..."
        #sys.stdout.flush()
        means, variances=tf.computeMaskedVolumeClassStatsCYTHON(warpedMask, warped, quantizationLevels, fixedQ)        
        means[0]=0
        means=np.array(means)
        variances=np.array(variances)
        sigmaField=variances[fixedQ]
        deltaField=means[fixedQ]-warped#########Delta-field using Arce's rule
        #--M step--
        g0, g1, g2=sp.gradient(warped)
        gradientField[:,:,:,0]=g0
        gradientField[:,:,:,1]=g1
        gradientField[:,:,:,2]=g2
        maxVariation=1+innerTolerance
        innerIter=0
        maxInnerIter=100
        displacement[...]=0
        #print "Iterating..."
        #sys.stdout.flush()
        while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)):
            innerIter+=1
            maxVariation=tf.iterateDisplacementField3DCYTHON(deltaField, sigmaField, gradientField,  lambdaDisplacement, totalDisplacement, displacement, residuals)
            opt=np.max(residuals)
            if(maxResidual<opt):
                maxResidual=opt
        #--accumulate displacement--
        #print "Exponential3D. Range D:", displacement.min(), displacement.max()
        #sys.stdout.flush()
        expd, inverseNone=tf.vector_field_exponential3D(displacement, False)
        expd=np.array(expd)
        #print "Range expd:", expd.min(), expd.max(), "Range TD:", totalDisplacement.min(), totalDisplacement.max()
        #print "Compose vector fields..."
        #sys.stdout.flush()
        totalDisplacement, stats=tf.compose_vector_fields3D(expd, totalDisplacement)
        totalDisplacement=np.array(totalDisplacement)
        #print "Composed rage:", totalDisplacement.min(), totalDisplacement.max()
        #sys.stdout.flush()
        #--check stop condition--
        nrm=np.sqrt(displacement[...,0]**2+displacement[...,1]**2+displacement[...,2]**2)
        #maxDisplacement=np.max(nrm)
        maxDisplacement=np.mean(nrm)
        if((maxDisplacement<outerTolerance)or(outerIter>=maxOuterIter)):
            finished=True
    print "Iter: ",outerIter, "Mean displacement:", maxDisplacement, "Max variation:",maxVariation, "Max residual:", maxResidual
    #sh=fixed.shape
    #rcommon.overlayImages(warped[:,sh[1]//2,:], fixed[:,sh[1]//2,:])
    #rcommon.overlayImages(warped[:,sh[1]//2,:]*warpedMask[:,sh[1]//2,:], fixed[:,sh[1]//2,:])
    #sys.stdout.flush()
    if(previousDisplacement!=None):
        #print 'Range TD:', totalDisplacement.min(), totalDisplacement.max(),'. Range PD:', previousDisplacement.min(), previousDisplacement.max()
        #sys.stdout.flush()
        return totalDisplacement-previousDisplacement
    return totalDisplacement
Exemplo n.º 14
0
     lambdaParam=0.9
     maxIter=100
     tolerance=1e-4
     if argc>3:
         lambdaParam=float(sys.argv[3])
     if argc>4:
         maxIter=int(sys.argv[4])
     if argc>5:
         tolerance=float(sys.argv[5])
     print 'Inverting displacement: ',dispName, '. With parameters: lambda=',lambdaParam, '. Maxiter=',maxIter, '. Tolerance=',tolerance,'...'
     inverse=np.array(tf.invert_vector_field3D(displacement, lambdaParam, maxIter, tolerance))
     invName="inv"+dispName
     print 'Saving inverse as:', invName
     np.save(invName, inverse)
     print 'Computing inversion error...'
     residual=np.array(tf.compose_vector_fields3D(displacement, inverse))
     residualName="res"+dispName
     print 'Saving residual as:', residualName
     np.save(residualName, residual)
     residual=np.sqrt(np.sum(residual**2,3))
     print "Mean residual norm:", residual.mean()," (",residual.std(), "). Max residual norm:", residual.max()
     sys.exit(0)
 elif(sys.argv[1]=='npy2nifti'):
     if argc<3:
         print 'File name expected.'
         sys.exit(0)
     fname=sys.argv[2]
     try:
         inputData=np.load(fname)
     except IOError:
         print 'Cannot open file:',fname