def endOfIteration(self):
        #print self.obj0
        self.iter += 1
        if (self.iter % self.saveRate) == 0:
            print 'saving...'
            (obj1, self.ct, self.St, self.grt, self.Jt) = self.objectiveFunDef(self.at, self.Afft, withTrajectory=True)
            dim2 = self.dim**2
            A = [np.zeros([self.Tsize, self.dim, self.dim]), np.zeros([self.Tsize, self.dim])]
            if self.affineDim > 0:
                for t in range(self.Tsize):
                    AB = np.dot(self.affineBasis, Afft[t])
                    A[0][t] = AB[0:dim2].reshape([self.dim, self.dim])
                    A[1][t] = AB[dim2:dim2+self.dim]
            (ct, St, grt)  = evol.gaussianDiffeonsEvolutionEuler(self.c0, self.S0, self.at, self.param.sigmaKernel, affine=A, withPointSet= self.gr0Fine)
 	    # (ct, St, grt, Jt)  = evol.gaussianDiffeonsEvolutionEuler(self.c0, self.S0, self.at, self.param.sigmaKernel, affine=A,
            #                                                         withPointSet = self.fv0Fine.vertices, withJacobian=True)
            imDef = diffeo.gridScalars(grid = self.im1)
            for kk in range(self.Tsize+1):
                imDef.data = diffeo.multilinInterp(self.im1.data, grt[kk, ...].transpose(range(-1, self.grt.ndim-2)))
                imDef.saveImg(self.outputDir +'/'+ self.saveFile+str(kk)+'.png', normalize=True)
                if self.dim==3:
                    gd.saveDiffeons(self.outputDir +'/'+ self.saveFile+'Diffeons'+str(kk)+'.vtk', self.ct[kk,...], self.St[kk,...])
                elif self.dim==2:
                    (R, detR) = gd.multiMatInverse1(self.St[kk,...], isSym=True)
                    diffx = self.gr1[..., np.newaxis, :] - self.ct[kk, ...]
                    betax = (R*diffx[..., np.newaxis, :]).sum(axis=-1)
                    dst = (betax * diffx).sum(axis=-1)
                    diffIm = np.minimum((255*(1-dst)*(dst < 1)).astype(float).sum(axis=-1), 255)
                    out = Image.fromarray(diffIm.astype(np.uint8))
                    out.save(self.outputDir +'/'+ self.saveFile+'Diffeons'+str(kk)+'.png')
        else:
            (obj1, self.ct, self.St, self.grt, self.Jt) = self.objectiveFunDef(self.at, self.Afft, withTrajectory=True)
def ImageMatchingDist(gr, J, im0, im1):
    #print gr.shape
    #print gr[10:20, 10:20, 0]
    #imdef0 = Img.interpolation.map_coordinates(im1.data, gr.transpose(range(-1, gr.ndim-1)), order=1, mode='nearest')
    imdef = diffeo.multilinInterp(im1.data, gr.transpose(range(-1, gr.ndim-1)))
    #print 'diff:', (imdef-imdef0).max()
    # print im1.data.min(), im1.data.max()
    # print imdef.min(), imdef.max()
    res = (((im0.data - imdef)**2)*np.exp(J)).sum()
    return res
def ImageMatchingGradient(gr, J, im0, im1, gradient=None):
    imdef = diffeo.multilinInterp(im1.data, gr.transpose(range(-1, gr.ndim-1)))
    #imdef = Img.interpolation.map_coordinates(im1.data, gr.transpose(range(-1, gr.ndim-1)), order=1, mode='nearest')
    # if not (gradient==None):
    #     gradIm1 = gradient
    # else:
    #     gradIm1 = diffeo.gradient(im1.data, im1.resol)
    # gradDef = np.zeros(gradIm1.shape)
    # for k in range(gradIm1.shape[0]):
    #     gradDef[k,...] = diffeo.multilinInterp(gradIm1[k, ...], gr.transpose(range(-1, gr.ndim-1)))
        #gradDef[k,...] = Img.interpolation.map_coordinates(gradIm1[k, ...], gr.transpose(range(-1, gr.ndim-1)), order=1, mode='nearest')
    gradDef = diffeo.multilinInterpGradient(im1.data, gr.transpose(range(-1, gr.ndim-1)))
    
    expJ = np.exp(J)
    pgr = ((-2*(im0.data-imdef)*expJ)*gradDef).transpose(np.append(range(1, gr.ndim), 0))
    pJ =  ((im0.data - imdef)**2)*expJ
    return pgr, pJ
    def __init__(self, Template=None, Target=None, Diffeons=None, EpsilonNet=None, DecimationTarget=1,
                 subsampleTemplate = 1, targetMargin=10, templateMargin=0,
                 DiffeonEpsForNet=None, DiffeonSegmentationRatio=None, zeroVar=False, fileTempl=None,
                 fileTarg=None, param=None, maxIter=1000, regWeight = 1.0, affineWeight = 1.0, verb=True,
                 rotWeight = None, scaleWeight = None, transWeight = None, testGradient=False, saveFile = 'evolution', affine = 'none', outputDir = '.'):
        if Template==None:
            if fileTempl==None:
                print 'Please provide a template image'
                return
            else:
                self.im0 = diffeo.gridScalars(filename=fileTempl)
        else:
            self.im0 = diffeo.gridScalars(grid=Template)
            #print self.im0.data.shape, Template.data.shape
        if Target==None:
            if fileTarg==None:
                print 'Please provide a target image'
                return
            else:
                self.im1 = diffeo.gridScalars(filename=fileTarg)
        else:
            self.im1 = diffeo.gridScalars(grid=Target)

            #zoom = np.minimum(np.array(self.im0.data.shape).astype(float)/np.array(self.im1.data.shape), np.ones(self.im0.data.ndim))
        zoom = np.array(self.im0.data.shape).astype(float)/np.array(self.im1.data.shape)
        print zoom
        self.im1.data = Img.interpolation.zoom(self.im1.data, zoom, order=0)

        # Include template in bigger image
        if templateMargin >0:
            I = range(-templateMargin, self.im0.data.shape[0]+templateMargin)
            for k in range(1, self.im0.data.ndim):
                I = (I, range(-templateMargin, self.im0.data.shape[k]+templateMargin))
            self.gr1 = np.array(np.meshgrid(*I, indexing='ij'))
            #print self.im1.data.shape
            self.im0.data = diffeo.multilinInterp(self.im0.data, self.gr1)

        # Include target in bigger image
        I = range(-targetMargin, self.im1.data.shape[0]+targetMargin)
        for k in range(1, self.im1.data.ndim):
            I = (I, range(-targetMargin, self.im1.data.shape[k]+targetMargin))
        self.gr1 = np.array(np.meshgrid(*I, indexing='ij'))
        #print self.im1.data.shape
        self.im1.data = diffeo.multilinInterp(self.im1.data, self.gr1)
        self.gr1 = self.gr1.transpose(np.append(range(1,self.gr1.ndim), 0)) +targetMargin
        #print self.im1.data.shape
        self.im0Fine = diffeo.gridScalars(grid=self.im0)
        self.saveRate = 5
        self.iter = 0
        self.gradEps = -1
        self.dim = self.im0.data.ndim
        self.setOutputDir(outputDir)
        self.maxIter = maxIter
        self.verb = verb
        self.testGradient = testGradient
        self.regweight = regWeight
        self.affine = affine
        affB = AffineBasis(self.dim, affine)
        self.affineDim = affB.affineDim
        self.affineBasis = affB.basis
        self.affineWeight = affineWeight * np.ones([self.affineDim, 1])
        if (len(affB.rotComp) > 0) & (rotWeight != None):
            self.affineWeight[affB.rotComp] = rotWeight
        if (len(affB.simComp) > 0) & (scaleWeight != None):
            self.affineWeight[affB.simComp] = scaleWeight
        if (len(affB.transComp) > 0) & (transWeight != None):
            self.affineWeight[affB.transComp] = transWeight

        if param==None:
            self.param = ImageMatchingParam()
        else:
            self.param = param
        self.dim = self.param.dimension
        #self.x0 = self.fv0.vertices
        if Diffeons==None:
            gradIm0 = np.sqrt((diffeo.gradient(self.im0.data, self.im0.resol)**2).sum(axis=0))
            m0 = stats.mquantiles(gradIm0, 0.75)/10. + 1e-5
            if DecimationTarget==None:
                DecimationTarget = 1
            gradIm0 = Img.filters.maximum_filter(gradIm0, DecimationTarget)
            I = range(templateMargin, self.im0.data.shape[0]-templateMargin, DecimationTarget)
            for k in range(1, self.im0.data.ndim):
                I = (I, range(templateMargin, self.im0.data.shape[k]-templateMargin, DecimationTarget))
            u = np.meshgrid(*I, indexing='ij')
            self.c0 = np.zeros([u[0].size, self.dim])
            for k in range(self.dim):
                self.c0[:,k] = u[k].flatten()
            # if self.dim == 1:
            #     self.c0 = range(0, self.im0.data.shape[0], DecimationTarget)
            # elif self.dim == 2:
            #     u = np.mgrid[0:self.im0.data.shape[0]:DecimationTarget, 0:self.im0.data.shape[1]:DecimationTarget]
            #     self.c0 = np.zeros([u[0].size, self.dim])
            #     self.c0[:,0] = u[0].flatten()
            #     self.c0[:,1] = u[1].flatten()
            # elif self.dim == 3:
            #     u = np.mgrid[0:self.im0.data.shape[0]:DecimationTarget, 0:self.im0.data.shape[1]:DecimationTarget, 0:self.im0.data.shape[2]:DecimationTarget]
            #     self.c0 = np.zeros([u[0].size, self.dim])
            #     self.c0[:,0] = u[0].flatten()
            #     self.c0[:,1] = u[1].flatten()
            #     self.c0[:,2] = u[2].flatten()
            gradIm0 = diffeo.multilinInterp(gradIm0, self.c0.T)
            #print gradIm0
            jj = 0
            for kk in range(self.c0.shape[0]):
                if gradIm0[kk] > m0:
                    self.c0[jj, :] = self.c0[kk, :]
                    jj += 1
            self.c0 = self.c0[0:jj, :]
            print 'keeping ', jj, ' diffeons' 
                #print self.im0.resol
            self.c0 = targetMargin - templateMargin + self.im0.origin + self.c0 * self.im0.resol
            self.S0 = np.tile( (DecimationTarget*np.diag(self.im0.resol)/2)**2, [self.c0.shape[0], 1, 1])
        else:
            (self.c0, self.S0, self.idx) = Diffeons

        if zeroVar:
	    self.S0 = np.zeros(self.S0.shape)

            #print self.c0
            #print self.S0
        if subsampleTemplate == None:
            subsampleTemplate = 1
        self.im0.resol *= subsampleTemplate
        self.im0.data = Img.filters.median_filter(self.im0.data, size=subsampleTemplate)
        I = range(0, self.im0.data.shape[0], subsampleTemplate)
        II = range(0, self.im0.data.shape[0])
        for k in range(1, self.im0.data.ndim):
            I = (I, range(0, self.im0.data.shape[k], subsampleTemplate))
            II = (II, range(0, self.im0.data.shape[k]))
        self.gr0= np.array(np.meshgrid(*I, indexing='ij'))
        self.gr0Fine= np.array(np.meshgrid(*II, indexing='ij'))
        self.im0.data = diffeo.multilinInterp(self.im0.data, self.gr0)
        self.gr0 = self.gr0.transpose(np.append(range(1,self.gr0.ndim), 0))
        self.gr0Fine = self.gr0Fine.transpose(np.append(range(1,self.gr0Fine.ndim), 0))
        #print self.gr0.shape
        # if self.dim == 1:
        #     self.im0.data = self.im0.data[0:self.im0.data.shape[0]:subsampleTemplate]
        #     self.gr0 = range(self.im0.data.shape[0])
        # elif self.dim == 2:
        #     self.im0.data = self.im0.data[0:self.im0.data.shape[0]:subsampleTemplate, 0:self.im0.data.shape[1]:subsampleTemplate]
        #     self.gr0 = np.mgrid[0:self.im0.data.shape[0], 0:self.im0.data.shape[1]].transpose((1, 2,0))
        # elif self.dim == 3:
        #     self.im0.data = self.im0.data[0:self.im0.data.shape[0]:subsampleTemplate, 0:self.im0.data.shape[1]:subsampleTemplate, 0:self.im0.data.shape[2]:subsampleTemplate]
        #     self.gr0 = np.mgrid[0:self.im0.data.shape[0], 0:self.im0.data.shape[1], 0:self.im0.data.shape[2]].transpose((1,2, 3, 0))
        self.gr0 = targetMargin-templateMargin+self.im1.origin + self.gr0 * self.im1.resol 
        self.gr0Fine = targetMargin-templateMargin+self.im1.origin + self.gr0Fine * self.im1.resol 
        self.J0 = np.log(self.im0.resol.prod()) * np.ones(self.im0.data.shape) 
	self.ndf = self.c0.shape[0]
        self.Tsize = int(round(1.0/self.param.timeStep))
        self.at = np.zeros([self.Tsize, self.c0.shape[0], self.dim])
        self.atTry = np.zeros([self.Tsize, self.c0.shape[0], self.dim])
        self.Afft = np.zeros([self.Tsize, self.affineDim])
        self.AfftTry = np.zeros([self.Tsize, self.affineDim])
        self.imt = np.tile(self.im0, np.insert(np.ones(self.dim), 0, self.Tsize+1))
        self.Jt = np.tile(self.J0, np.insert(np.ones(self.dim), 0, self.Tsize+1))
        self.grt = np.tile(self.gr0, np.insert(np.ones(self.dim+1), 0, self.Tsize+1))
        self.ct = np.tile(self.c0, [self.Tsize+1, 1, 1])
        self.St = np.tile(self.S0, [self.Tsize+1, 1, 1, 1])
        print 'error type:', self.param.errorType
        self.obj = None
        self.objTry = None
        self.gradCoeff = self.ndf
        self.saveFile = saveFile
        self.gradIm1 = diffeo.gradient(self.im1.data, self.im1.resol)
        self.im0.saveImg(self.outputDir+'/Template.png', normalize=True)
        self.im1.saveImg(self.outputDir+'/Target.png', normalize=True)