def  objectiveFunDef(self, at, Afft, withTrajectory = False, withJacobian=False, initial = None):
        if initial == None:
            x0 = self.x0
            c0 = self.c0
            S0 = self.S0
	    if self.dcurr:
		b0 = self.b0
                xS0 = self.xS0
        else:
            x0 = self.x0
	    if self.dcurr:
		(c0, S0, b0, xS0) = initial
	    else:
		(c0, S0) = initial
        param = self.param
        timeStep = 1.0/self.Tsize
        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]
	if withJacobian:
	    if self.dcurr:
		(ct, St, bt, xt, xSt, Jt)  = evol.gaussianDiffeonsEvolutionEuler(c0, S0, at, param.sigmaKernel, affine=A, withJacobian=True, withNormals=b0, withDiffeonSet=(x0, xS0))
            else:
		(ct, St, xt, Jt)  = evol.gaussianDiffeonsEvolutionEuler(c0, S0, at, param.sigmaKernel, affine=A, withPointSet = x0, withJacobian=True)
        else:
	    if self.dcurr:
		(ct, St, bt, xt, xSt)  = evol.gaussianDiffeonsEvolutionEuler(c0, S0, at, param.sigmaKernel, affine=A, withNormals=b0, withDiffeonSet=(x0, xS0))
            else:
		(ct, St, xt)  = evol.gaussianDiffeonsEvolutionEuler(c0, S0, at, param.sigmaKernel, affine=A, withPointSet = x0)

        #print xt[-1, :, :]
        #print obj
        obj=0
        #print St.shape
        for t in range(self.Tsize):
            c = np.squeeze(ct[t, :, :])
            S = np.squeeze(St[t, :, :, :])
            a = np.squeeze(at[t, :, :])
            #rzz = kfun.kernelMatrix(param.KparDiff, z)
            rcc = gd.computeProducts(c, S, param.sigmaKernel)
            obj = obj + self.regweight*timeStep*np.multiply(a, np.dot(rcc,a)).sum()
            if self.affineDim > 0:
                obj +=  timeStep * np.multiply(self.affineWeight.reshape(Afft[t].shape), Afft[t]**2).sum()
            #print xt.sum(), at.sum(), obj
        if withJacobian:
            if self.dcurr:
                return obj, ct, St, bt, xt, xSt, Jt
            else:
                return obj, ct, St, xt, Jt
        elif withTrajectory:
            if self.dcurr:
                return obj, ct, St, bt, xt, xSt
            else:
                return obj, ct, St, xt
        else:
            return obj
    def endOfIteration(self):
        #print self.obj0
        self.iter += 1
        if (self.iter % self.saveRate == 0) :
            if self.dcurr:
                print 'saving...'
                (obj1, self.ct, self.St, self.bt, self.xt, self.xSt, Jt) = self.objectiveFunDef(self.at, self.Afft, withTrajectory=True, withJacobian=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, xt, Jt)  = evol.gaussianDiffeonsEvolutionEuler(self.c0, self.S0, self.at, self.param.sigmaKernel, affine=A,
                                                                        withPointSet = self.fv0Fine.vertices, withJacobian=True)
                fvDef = surfaces.Surface(surf=self.fv0Fine)
                for kk in range(self.Tsize+1):
                    self.fvDef.updateVertices(np.squeeze(self.xt[kk, :, :]))
                    fvDef.updateVertices(np.squeeze(xt[kk, :, :]))
                    # foo = (gd.diffeonCurrentNormDef(self.xt[kk], self.xSt[kk], self.bt[kk], self.fvDef, self.param.KparDist.sigma)
                    #        + gd.diffeonCurrentNorm0(self.fvDef, self.param.KparDist))/ (self.param.sigmaError**2)
                    # print foo
                    fvDef.saveVTK(self.outputDir +'/'+ self.saveFile+str(kk)+'.vtk', scalars = Jt[kk, :], scal_name='Jacobian')
                    gd.saveDiffeons(self.outputDir +'/'+ self.saveFile+'Diffeons'+str(kk)+'.vtk', self.ct[kk,:,:], self.St[kk,:,:,:])
                    self.saveB(self.outputDir +'/'+ self.saveFile+'Bt'+str(kk)+'.vtk', self.xt[kk,:,:], self.bt[kk,:,:])
            else:
                (obj1, self.ct, self.St, self.xt) = self.objectiveFunDef(self.at, self.Afft, withTrajectory=True)
                self.fvDef.updateVertices(np.squeeze(self.xt[-1, :, :]))
                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, xt, Jt)  = evol.gaussianDiffeonsEvolutionEuler(self.c0, self.S0, self.at, self.param.sigmaKernel, affine=A,
                                                                        withPointSet = self.fv0Fine.vertices, withJacobian=True)
                fvDef = surfaces.Surface(surf=self.fv0Fine)
                for kk in range(self.Tsize+1):
                    fvDef.updateVertices(np.squeeze(xt[kk, :, :]))
                    fvDef.saveVTK(self.outputDir +'/'+ self.saveFile+str(kk)+'.vtk', scalars = Jt[kk, :], scal_name='Jacobian')
                        #self.fvDef.saveVTK(self.outputDir +'/'+ self.saveFile+str(kk)+'.vtk', scalars = self.idx, scal_name='Labels')
                    gd.saveDiffeons(self.outputDir +'/'+ self.saveFile+'Diffeons'+str(kk)+'.vtk', self.ct[kk,:,:], self.St[kk,:,:,:])

            #print self.bt

        else:
            if self.dcurr:
                (obj1, self.ct, self.St, self.bt, self.xt, self.xSt) = self.objectiveFunDef(self.at, self.Afft, withTrajectory=True)
            else:
                (obj1, self.ct, self.St, self.xt) = self.objectiveFunDef(self.at, self.Afft, withTrajectory=True)
                self.fvDef.updateVertices(np.squeeze(self.xt[-1, :, :]))
    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 restart(self, EpsilonNet=None, DiffeonEpsForNet=None, DiffeonSegmentationRatio=None, DecimationTarget=None):
        if EpsilonNet==None:
            if DecimationTarget==None:
                if DiffeonEpsForNet==None:
                    if DiffeonSegmentationRatio==None:
                        c0 = np.copy(self.x0) ;
                        S0 = np.zeros([self.x0.shape[0], self.x0.shape[1], self.x0.shape[1]])
                        #net = range(c0.shape[0])
                        idx = range(c0.shape[0])
                    else:
                        (c0, S0, idx) = gd.generateDiffeonsFromSegmentation(self.fv0, DiffeonSegmentationRatio)
                        #self.S0 *= self.param.sigmaKernel**2;
                else:
                    (c0, S0, idx) = gd.generateDiffeonsFromNet(self.fv0, DiffeonEpsForNet)
            else:
                (c0, S0, idx) = gd.generateDiffeonsFromDecimation(self.fv0, DecimationTarget)
        else:
            net = EspilonNet[2] 
            (c0, S0, idx) = gd.generateDiffeons(self.fv0, EpsilonNet[0], EpsilonNet[1])

        (ctPrev, StPrev, ct, St) = evol.gaussianDiffeonsEvolutionEuler(self.c0, self.S0, self.at, self.param.sigmaKernel, withDiffeonSet=(c0, S0))
        at = np.zeros([self.Tsize, c0.shape[0], self.x0.shape[1]])
        #fvDef = surfaces.Surface(surf=self.fvDef)
        for t in range(self.Tsize):
            g1 = gd.computeProducts(np.squeeze(ct[t,:,:]),np.squeeze(St[t,:,:]), self.param.sigmaKernel) 
            g2 = gd.computeProductsAsym(np.squeeze(ct[t,:,:]),np.squeeze(St[t,:,:]), np.squeeze(ctPrev[t,:,:]),np.squeeze(StPrev[t,:,:]), self.param.sigmaKernel)
            g2a = np.dot(g2, np.squeeze(self.at[t, :, :]))
            at[t, :, :] = LA.solve(g1, g2a)
            g0 = gd.computeProducts(np.squeeze(ctPrev[t,:,:]),np.squeeze(StPrev[t,:,:]), self.param.sigmaKernel)
            n0 = np.multiply(self.at[t, :, :], np.dot(g0, self.at[t, :, :])).sum()
            n1 = np.multiply(at[t, :, :], np.dot(g1, at[t, :, :])).sum()
            print 'norms: ', n0, n1
            # fvDef.updateVertices(np.squeeze(self.xt[t, :, :]))
            # (AV, AF) = fvDef.computeVertexArea()
            # weights = np.zeros([c0.shape[0], self.c0.shape[0]])
            # diffArea = np.zeros(self.c0.shape[0])
            # diffArea2 = np.zeros(c0.shape[0])
            # for k in range(self.npt):
            #     diffArea[self.idx[k]] += AV[k] 
            #     diffArea2[idx[k]] += AV[k]
            #     weights[idx[k], self.idx[k]] += AV[k]
            # weights /= diffArea.reshape([1, self.c0.shape[0]])
            # at[t] = np.dot(weights, self.at[t, :, :])
        self.c0 = c0
        self.idx = idx
        self.S0 = S0
        self.at = at
        self.ndf = self.c0.shape[0]
        self.ct = np.tile(self.c0, [self.Tsize+1, 1, 1])
        self.St = np.tile(self.S0, [self.Tsize+1, 1, 1, 1])
        if self.dcurr:
	    self.b0 = gd.approximateSurfaceCurrent(self.c0, self.S0, self.fv0, self.param.KparDist.sigma)
            #print self.b0.shape
            self.bt = np.tile(self.b0, [self.Tsize+1, 1, 1])
        self.obj = None
        self.objTry = None
        self.gradCoeff = self.ndf
        self.optimizeMatching()