def endOfIteration(self):
     (obj1, self.xt, Jt, self.cval) = self.objectiveFunDef(self.at, self.Afft, withJacobian=True)
     logging.info('mean constraint %f %f' %(np.sqrt((self.cval**2).sum()/self.cval.size), np.fabs(self.cval).sum() / self.cval.size))
     #self.testConstraintTerm(self.xt, self.nut, self.at, self.Afft)
     nn = 0 ;
     for k in range(self.nsurf):
         AV0 = self.fv0[k].computeVertexArea()
         n1 = self.xt[k].shape[1] ;
         for kk in range(self.Tsize+1):
             self.fvDefB[k].updateVertices(np.squeeze(self.xt[-1][kk, nn:nn+n1, :]))
             AV = self.fvDefB[k].computeVertexArea()
             AV = (AV[0]/AV0[0])-1
             #self.fvDefB[k].saveVTK(self.outputDir +'/'+ self.saveFile+str(k)+'Out'+str(kk)+'.vtk', scalars = Jt[-1][kk, nn:nn+n1], scal_name='Jacobian')
             vf = surfaces.vtkFields() ;
             vf.scalars.append('Jacobian') ;
             vf.scalars.append(np.exp(Jt[-1][kk, nn:nn+n1])-1)
             vf.scalars.append('Jacobian_T') ;
             vf.scalars.append(AV[:,0])
             vf.scalars.append('Jacobian_N') ;
             vf.scalars.append(np.exp(Jt[-1][kk, nn:nn+n1])/(AV[:,0]+1)-1)
             #self.fvDefB[k].saveVTK(self.outputDir +'/'+ self.saveFile+str(k)+'Out'+str(kk)+'.vtk', scalars = AV[:,0], scal_name='Jacobian')
             self.fvDefB[k].saveVTK2(self.outputDir +'/'+ self.saveFile+str(k)+'Out'+str(kk)+'.vtk', vf)
             self.fvDef[k].updateVertices(np.squeeze(self.xt[k][kk, :, :]))
             AV = self.fvDef[k].computeVertexArea()
             AV = (AV[0]/AV0[0])-1
             vf = surfaces.vtkFields() ;
             vf.scalars.append('Jacobian') ;
             vf.scalars.append(np.exp(Jt[k][kk, :])-1)
             vf.scalars.append('Jacobian_T') ;
             vf.scalars.append(AV[:,0])
             vf.scalars.append('Jacobian_N') ;
             vf.scalars.append(np.exp(Jt[k][kk, :])/(AV[:,0]+1)-1)
             #self.fvDef[k].saveVTK(self.outputDir +'/'+self.saveFile+str(k)+'In'+str(kk)+'.vtk', scalars = Jt[k][kk, :], scal_name='Jacobian')
             #self.fvDef[k].saveVTK(self.outputDir +'/'+self.saveFile+str(k)+'In'+str(kk)+'.vtk', scalars = AV[:,0], scal_name='Jacobian')
             self.fvDef[k].saveVTK2(self.outputDir +'/'+self.saveFile+str(k)+'In'+str(kk)+'.vtk', vf)
         nn += n1
    def endOfIteration(self):
        self.iter += 1
        if self.iter >= self.affBurnIn:
            self.coeffAff = self.coeffAff2
        if (self.iter % self.saveRate == 0):
            logging.info('Saving surfaces...')
            (obj1, self.xt) = self.objectiveFunDef(self.at, self.Afft, withTrajectory=True)
            for k in range(self.nTarg):
                self.fvDef[k].updateVertices(np.squeeze(self.xt[(k+1)*self.Tsize1, :, :]))
            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, self.Afft[t])
                    A[0][t] = AB[0:dim2].reshape([self.dim, self.dim])
                    A[1][t] = AB[dim2:dim2+self.dim]
                    
            (xt, ft, Jt)  = evol.landmarkDirectEvolutionEuler(self.x0, self.at, self.param.KparDiff, affine=A,
                                                           withPointSet = self.fv0Fine.vertices, withJacobian=True)

            if self.affine=='euclidean' or self.affine=='translation':
                f = surfaces.Surface(surf=self.fv0Fine)
                X = self.affB.integrateFlow(self.Afft)
                displ = np.zeros(self.x0.shape[0])
                dt = 1.0 /self.Tsize ;
                for t in range(self.Tsize+1):
                    U = la.inv(X[0][t])
                    yyt = np.dot(xt[t,...] - X[1][t, ...], U.T)
                    zt = np.dot(ft[t,...] - X[1][t, ...], U.T)
                    if t < self.Tsize:
                        at = np.dot(self.at[t,...], U.T)
                        vt = self.param.KparDiff.applyK(yyt, at, firstVar=zt)
                    f.updateVertices(zt)
                    vf = surfaces.vtkFields() ;
                    vf.scalars.append('Jacobian') ;
                    vf.scalars.append(np.exp(Jt[t, :])-1)
                    vf.scalars.append('displacement')
                    vf.scalars.append(displ)
                    vf.vectors.append('velocity') ;
                    vf.vectors.append(vt)
                    nu = self.fv0ori*f.computeVertexNormals()
                    displ += dt * (vt*nu).sum(axis=1)
                    f.saveVTK2(self.outputDir +'/'+self.saveFile+'Corrected'+str(t)+'.vtk', vf)

                for k,fv in enumerate(self.fv1):
                    f = surfaces.Surface(surf=fv)
                    U = la.inv(X[0][(k+1)*self.Tsize1])
                    yyt = np.dot(f.vertices - X[1][(k+1)*self.Tsize1, ...], U.T)
                    f.updateVertices(yyt)
                    f.saveVTK(self.outputDir +'/Target'+str(k)+'Corrected.vtk')
            
            fvDef = surfaces.Surface(surf=self.fv0Fine)
            AV0 = fvDef.computeVertexArea()
            nu = self.fv0ori*self.fv0Fine.computeVertexNormals()
            #v = self.v[0,...]
            displ = np.zeros(self.npt)
            dt = 1.0 /self.Tsize ;
            v = self.param.KparDiff.applyK(ft[0,...], self.at[0,...], firstVar=self.xt[0,...])
            for kk in range(self.Tsize+1):
                fvDef.updateVertices(np.squeeze(ft[kk, :, :]))
                AV = fvDef.computeVertexArea()
                AV = (AV[0]/AV0[0])-1
                vf = surfaces.vtkFields() ;
                vf.scalars.append('Jacobian') ;
                vf.scalars.append(np.exp(Jt[kk, :])-1)
                vf.scalars.append('Jacobian_T') ;
                vf.scalars.append(AV[:,0])
                vf.scalars.append('Jacobian_N') ;
                vf.scalars.append(np.exp(Jt[kk, :])/(AV[:,0]+1)-1)
                vf.scalars.append('displacement')
                vf.scalars.append(displ)
                displ += dt * (v*nu).sum(axis=1)
                if kk < self.Tsize:
                    nu = self.fv0ori*fvDef.computeVertexNormals()
                    v = self.param.KparDiff.applyK(ft[kk,...], self.at[kk,...], firstVar=self.xt[kk,...])
                    #v = self.v[kk,...]
                    kkm = kk
                else:
                    kkm = kk-1
                vf.vectors.append('velocity') ;
                vf.vectors.append(self.v[kkm,:])
                fvDef.saveVTK2(self.outputDir +'/'+ self.saveFile+str(kk)+'.vtk', vf)
        else:
            (obj1, self.xt) = self.objectiveFunDef(self.at, self.Afft, withTrajectory=True)
            for k in range(self.nTarg):
                self.fvDef[k].updateVertices(np.squeeze(self.xt[(k+1)*self.Tsize1, :, :]))
    def endOfIteration(self):
        self.iter += 1
        if self.iter >= self.affBurnIn:
            self.coeffAff = self.coeffAff2
        (obj1, self.xt, Jt, self.cval) = self.objectiveFunDef(self.at, self.Afft, withJacobian=True)
        logging.info('mean constraint %f %f' %(np.sqrt((self.cstr**2).sum()/self.cval.size), np.fabs(self.cstr).sum() / self.cval.size))
        self.fvInit.updateVertices(self.x0)

        if self.affine=='euclidean' or self.affine=='translation':
            f = surfaces.Surface(surf=self.fvInit)
            X = self.affB.integrateFlow(self.Afft)
            displ = np.zeros(self.npt)
            dt = 1.0 /self.Tsize ;
            for t in range(self.Tsize+1):
                U = la.inv(X[0][t])
                yt = np.dot(self.xt[t,...] - X[1][t, ...], U.T)
                if t < self.Tsize:
                    at = np.dot(self.at[t,...], U.T)
                    vt = self.param.KparDiff.applyK(yt, at)
                f.updateVertices(yt)
                vf = surfaces.vtkFields() ;
                vf.scalars.append('Jacobian') ;
                vf.scalars.append(np.exp(Jt[t, :])-1)
                vf.scalars.append('displacement')
                vf.scalars.append(displ)
                vf.vectors.append('velocity') ;
                vf.vectors.append(vt)
                nu = self.fv0ori*f.computeVertexNormals()
                displ += dt * (vt*nu).sum(axis=1)
                f.saveVTK2(self.outputDir +'/'+self.saveFile+'Corrected'+str(t)+'.vtk', vf)
            f = surfaces.Surface(surf=self.fv1)
            yt = np.dot(f.vertices - X[1][-1, ...], U.T)
            f.updateVertices(yt)
            f.saveVTK(self.outputDir +'/TargetCorrected.vtk')
                
                
        #self.testConstraintTerm(self.xt, self.at, self.Afft)
        nn = 0 ;
        AV0 = self.fvInit.computeVertexArea()
        nu = self.fv0ori*self.fvInit.computeVertexNormals()
        v = self.v[0,...]
        displ = np.zeros(self.npt)
        dt = 1.0 /self.Tsize ;
        n1 = self.xt.shape[1] ;
        for kk in range(self.Tsize+1):
            self.fvDef.updateVertices(np.squeeze(self.xt[kk, :, :]))
            AV = self.fvDef.computeVertexArea()
            AV = (AV[0]/AV0[0])-1
            vf = surfaces.vtkFields() ;
            vf.scalars.append('Jacobian') ;
            vf.scalars.append(np.exp(Jt[kk, :])-1)
            vf.scalars.append('Jacobian_T') ;
            vf.scalars.append(AV[:,0])
            vf.scalars.append('Jacobian_N') ;
            vf.scalars.append(np.exp(Jt[kk, :])/(AV[:,0]+1)-1)
            vf.scalars.append('displacement')
            vf.scalars.append(displ)
            displ += dt * (v*nu).sum(axis=1)
            if kk < self.Tsize:
                nu = self.fv0ori*self.fvDef.computeVertexNormals()
                v = self.v[kk,...]
                kkm = kk
            else:
                kkm = kk-1
            vf.scalars.append('constraint') ;
            vf.scalars.append(self.cstr[kkm,:])
            vf.vectors.append('velocity') ;
            vf.vectors.append(self.v[kkm,:])
            vf.vectors.append('normals') ;
            vf.vectors.append(self.nu[kkm,:])
            self.fvDef.saveVTK2(self.outputDir +'/'+self.saveFile+str(kk)+'.vtk', vf)