def endOfIteration(self):
     self.iter += 1
     if self.iter % self.saveRate == 0:
         (obj1, self.xt, self.at, self.yt, self.vt) = self.objectiveFunDef(self.rhot, withTrajectory=True)
         for k in range(self.nTarg):
             self.fvDef[k].updateVertices(np.squeeze(self.xt[(k + 1) * self.Tsize1, :, :]))
         (xt, at, yt, vt, zt, Jt) = evol.secondOrderFiberEvolution(
             self.x0,
             self.a0,
             self.y0,
             self.v0,
             self.rhot,
             self.param.KparDiff,
             withPointSet=self.fv0Fine.vertices,
             withJacobian=True,
         )
         fvDef = surfaces.Surface(surf=self.fv0Fine)
         for kk in range(self.Tsize + 1):
             fvDef.updateVertices(np.squeeze(zt[kk, :, :]))
             fvDef.saveVTK(
                 self.outputDir + "/" + self.saveFile + str(kk) + ".vtk", scalars=Jt[kk, :], scal_name="Jacobian"
             )
             vn = np.squeeze(vt[kk, ...])
             vn = vn / np.sqrt((vn ** 2).sum(axis=1))[:, np.newaxis]
             savePoints(self.outputDir + "/fiber_" + self.saveFile + str(kk) + ".vtk", yt[kk, ...], vector=vn)
             # self.fvDef.saveVTK(self.outputDir +'/'+ self.saveFile+str(kk)+'.vtk', scalars = self.idx, scal_name='Labels')
     else:
         (obj1, self.xt, self.at, self.yt, self.vt) = self.objectiveFunDef(self.rhot, withTrajectory=True)
         for k in range(self.nTarg):
             self.fvDef[k].updateVertices(np.squeeze(self.xt[(k + 1) * self.Tsize1, :, :]))
    def objectiveFunDef(self, rhot, withTrajectory=False, withJacobian=False, Init=None):
        if Init == None:
            x0 = self.x0
            y0 = self.y0
            v0 = self.v0
            a0 = self.a0
        else:
            x0 = Init[0]
            y0 = Init[2]
            v0 = Init[3]
            a0 = Init[1]

        param = self.param
        timeStep = 1.0 / self.Tsize
        dim2 = self.dim ** 2
        # print a0.shape
        if withJacobian:
            (xt, at, yt, vt, Jt) = evol.secondOrderFiberEvolution(
                x0, a0, y0, v0, rhot, param.KparDiff, withJacobian=True
            )
        else:
            (xt, at, yt, vt) = evol.secondOrderFiberEvolution(x0, a0, y0, v0, rhot, param.KparDiff)
        # print xt[-1, :, :]
        # print obj
        obj = 0
        for t in range(self.Tsize):
            v = np.squeeze(vt[t, :, :])
            rho = np.squeeze(rhot[t, :])

            obj = obj + timeStep * ((rho ** 2) * (v ** 2).sum(axis=1)).sum() / 2
            # print xt.sum(), at.sum(), obj
        if withJacobian:
            return obj, xt, at, yt, vt, Jt
        elif withTrajectory:
            return obj, xt, at, yt, vt
        else:
            return obj
def compute(createSurfaces=True):

    if createSurfaces:
        [x,y,z] = np.mgrid[0:200, 0:200, 0:200]/100.
        ay = np.fabs(y-1)
        az = np.fabs(z-1)
        ax = np.fabs(x-0.5)
        s2 = np.sqrt(2)
        c1 = np.sqrt(0.06)
        c2 = np.sqrt(0.045)
        c3 = 0.1

        I1 = np.minimum(c1**2 - (ax**2 + 0.5*ay**2 + az**2), np.minimum((ax**2 + 0.5*ay**2 + az**2)-c2**2, 1+c3-y)) 
        fv1 = Surface() ;
        fv1.Isosurface(I1, value = 0, target=1000, scales=[1, 1, 1], smooth=0.01)


        #return fv1

        #s1 = 1.375
        #s2 = 2
        s1 = 1.1
        s2 = 1.2
        p = 1.75
        I1 = np.minimum(c1**p/s1 - ((ax**p + 0.5*ay**p + az**p)), np.minimum((s2*ax**p + s2*0.5*ay**p + s2*az**p)-c2**p/s1, 1+c3/s1-y))  
        fv2 = Surface() ;
        fv2.Isosurface(I1, value = 0, target=1000, scales=[1, 1, 1], smooth=0.01)
        
        fv2.vertices[:,1] += 15 - 15/s1

        s1 *= 1.1
        s2 *= 1.2
        I1 = np.minimum(c1**p/s1 - ((ax**p + 0.5*ay**p + az**p)), np.minimum((s2*ax**p + s2*0.5*ay**p + s2*az**p)-c2**p/s1, 1+c3/s1-y))  
        fv3 = Surface() ;
        fv3.Isosurface(I1, value = 0, target=1000, scales=[1, 1, 1], smooth=0.01)
        
        fv3.vertices[:,1] += 15 - 15/s1

        
        fv1.saveVTK('/Users/younes/Development/Results/Fibers/fv1.vtk')
        fv2.saveVTK('/Users/younes/Development/Results/Fibers/fv2.vtk')
        fv3.saveVTK('/Users/younes/Development/Results/Fibers/fv3.vtk')
    else:
        fv1 = Surface(filename='/Users/younes/Development/Results/Fibers/fv1.vtk')
        fv2  = Surface(filename='/Users/younes/Development/Results/Fibers/fv2.vtk')
        fv3  = Surface(filename='/Users/younes/Development/Results/Fibers/fv3.vtk')

    ## Long axis is 0y
    V1 = fv1.vertices/100 - [0,1,1]
    N1 = fv1.computeVertexNormals()
    
    sel0 = V1[:,1] < 0.95*V1[:,1].max()
    I0 = np.nonzero(sel0)
    I0 = I0[0]
    V1 = V1[I0, :]
    N1 = N1[I0, :]


    QNN = (N1[:,0]-0.5)**2 + 0.5*N1[:,1]**2 + N1[:,2]**2
    QVV = (V1[:,0]-0.5)**2 + 0.5*V1[:,1]**2 + V1[:,2]**2
    QNV = (N1[:,0]-0.5)*(V1[:,0]-0.5) + 0.5*N1[:,1]*V1[:,1] + N1[:,2]*V1[:,2]

    #exterior wall
    sel1 = np.logical_and(np.fabs(QVV-0.06) < 0.01, (np.fabs(N1[:,1]) < 0.8))
    I1 = np.nonzero(sel1)
    I1= I1[0]

    V11 = V1[I1, :]
    N11 = N1[I1, :]
    a = np.zeros(len(I1))
    a = (-QNV[I1] - np.sqrt(QNV[I1]**2 - QNN[I1]*(QVV[I1]-0.0525)))/QNN[I1]
    N = V1.shape[0]
    M = V1.shape[0] + len(I1)
    #M = M1 + len(I1)
    y0 = np.zeros([M,3])
    v0 = np.zeros([M,3])
    nz = np.zeros([N, 3])
    nz2 = np.zeros([N, 3])
    y0[0:N, :] = V1 
    #y0[N:M1, :] = V11 + 0.5*a[:,np.newaxis]*N11
    y0[N:M, :] = V11 + a[:,np.newaxis]*N11
    nz[:, 0] = -N1[:, 2]
    nz[:, 2] = N1[:, 0]
    nz2[:,0] = N1[:,0]*N1[:,1]
    nz2[:,1] = -(N1[:,0]**2 + N1[:,2]**2)
    nz2[:,2] = N1[:,2]*N1[:,1]
    nz = nz / (1e-5 + np.sqrt((nz**2).sum(axis=1)[:,np.newaxis]))
    nz2 = nz2 / (1e-5 + np.sqrt((nz2**2).sum(axis=1)[:,np.newaxis]))
    theta = 2*np.pi/3
    psi = 0 #np.pi/12
    c = np.cos(theta)
    s = np.sin(theta)
    c0 = np.cos(psi)
    s0 = np.sin(psi)
    v0[0:N, :] = -c*nz - s*nz2 
    v0[I1,:] *= -1
    #v0[I1, :] += 2*s*nz2[I1,:]
    v0[N:M, :] = nz[I1, :]
    #v0[M1:M, :] = -c*nz[I1,:] + s*nz2[I1,:]
    v0[0:N,:] = c0*v0[0:N, :] - s0*N1
     
    K1 = Kernel(name='laplacian', sigma = 10.0)
    y0 = 100*(y0+[0,1,1])
    pointSets.savePoints('/Users/younes/Development/Results/Fibers/Ellipses/fibers.vtk', y0, vector=v0)

    sm = SurfaceMatchingParam(timeStep=0.1, KparDiff=K1, sigmaDist=5, sigmaError=1., errorType='measure')
    f = SurfaceMatching(Template=fv1, Target=[fv2,fv3], Fiber=(y0,v0), outputDir='/Users/younes/Development/Results/Fibers/Ellipses',param=sm, testGradient=False,
                        #subsampleTargetSize = 500,
                         maxIter=1000)

    xt, at, yt, vt = pointEvolution.secondOrderFiberEvolution(fv1.vertices, np.zeros(y0.shape), y0, v0, -10*np.ones([10, y0.shape[0]]), K1)
    fvDef = Surface(surf=fv1)
    for k in range(xt.shape[0]):
        fvDef.updateVertices(xt[k, ...])
        fvDef.saveVTK('/Users/younes/Development/Results/Fibers/fvDef'+str(k)+'.vtk')

        #return
    f.optimizeMatching()


    return f, f23
    def __init__(
        self,
        Template=None,
        Target=None,
        Fiber=None,
        fileTempl=None,
        fileTarg=None,
        fileFiber=None,
        param=None,
        initialMomentum=None,
        maxIter=1000,
        regWeight=1.0,
        verb=True,
        subsampleTargetSize=-1,
        testGradient=True,
        saveFile="evolution",
        outputDir=".",
    ):
        if Template == None:
            if fileTempl == None:
                print "Please provide a template surface"
                return
            else:
                self.fv0 = surfaces.Surface(filename=fileTempl)
        else:
            self.fv0 = surfaces.Surface(surf=Template)
        if Target == None:
            if fileTarg == None:
                print "Please provide a list of target surfaces"
                return
            else:
                self.fv1 = []
                for f in fileTarg:
                    self.fv1.append(surfaces.Surface(filename=f))
        else:
            self.fv1 = []
            for s in Target:
                self.fv1.append(surfaces.Surface(surf=s))

        if Fiber == None:
            if fileFiber == None:
                print "Please provide fiber structure"
                return
            else:
                (self.y0, self.v0) = read3DVectorField(fileFiber)
        else:
            self.y0 = np.copy(Fiber[0])
            self.v0 = np.copy(Fiber[1])

            # print np.fabs(self.fv1.surfel-self.fv0.surfel).max()

        self.nTarg = len(self.fv1)
        self.saveRate = 10
        self.iter = 0
        self.outputDir = outputDir
        if not os.access(outputDir, os.W_OK):
            if os.access(outputDir, os.F_OK):
                print "Cannot save in " + outputDir
                return
            else:
                os.mkdir(outputDir)
        self.dim = self.fv0.vertices.shape[1]
        self.maxIter = maxIter
        self.verb = verb
        self.testGradient = testGradient
        self.regweight = regWeight

        if param == None:
            self.param = SurfaceMatchingParam()
        else:
            self.param = param

        self.fv0Fine = surfaces.Surface(surf=self.fv0)
        if subsampleTargetSize > 0:
            self.fv0.Simplify(subsampleTargetSize)
            v0 = self.fv0.surfVolume()
            for s in self.fv1:
                v1 = s.surfVolume()
                if v0 * v1 < 0:
                    s.flipFaces()
            print "simplified template", self.fv0.vertices.shape[0]
        self.x0 = self.fv0.vertices
        self.fvDef = []
        for k in range(self.nTarg):
            self.fvDef.append(surfaces.Surface(surf=self.fv0))
        self.npt = self.y0.shape[0]
        self.Tsize1 = int(round(1.0 / self.param.timeStep))
        self.Tsize = self.nTarg * self.Tsize1
        self.rhot = np.zeros([self.Tsize, self.y0.shape[0]])
        self.rhotTry = np.zeros([self.Tsize, self.y0.shape[0]])
        if initialMomentum == None:
            self.xt = np.tile(self.x0, [self.Tsize + 1, 1, 1])
            self.a0 = np.zeros([self.y0.shape[0], self.x0.shape[1]])
            self.at = np.tile(self.a0, [self.Tsize + 1, 1, 1])
            self.yt = np.tile(self.y0, [self.Tsize + 1, 1, 1])
            self.vt = np.tile(self.v0, [self.Tsize + 1, 1, 1])
        else:
            self.a0 = initialMomentum
            (self.xt, self.at, self.yt, self.vt) = evol.secondOrderFiberEvolution(
                self.x0, self.a0, self.y0, self.v0, self.rhot, self.param.KparDiff
            )

        self.obj = None
        self.objTry = None
        self.gradCoeff = self.fv0.vertices.shape[0]
        self.saveFile = saveFile
        self.fv0.saveVTK(self.outputDir + "/Template.vtk")
        for k, s in enumerate(self.fv1):
            s.saveVTK(self.outputDir + "/Target" + str(k) + ".vtk")