diff --git a/vtk_py/BiV.geo b/vtk_py/BiV.geo new file mode 100644 index 0000000..cb80a16 --- /dev/null +++ b/vtk_py/BiV.geo @@ -0,0 +1,54 @@ +Geometry.HideCompounds = 1; + +Mesh.CharacteristicLengthFactor = <> ;// Fine + +Mesh.Algorithm = 6; // (1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=bamg, 8=delquad) (Default=2) +Mesh.RecombineAll = 0; + +Mesh.RemeshAlgorithm = 1; // (0=no split, 1=automatic, 2=automatic only with metis) (Default=0) + +Mesh.RemeshParametrization = 7; // (0=harmonic_circle, 1=conformal_spectral, 2=rbf, 3=harmonic_plane, 4=convex_circle, 5=convex_plane, 6=harmonic square, 7=conformal_fe) (Default=4) + +Mesh.Algorithm3D = 4; // (1=Delaunay, 4=Frontal, 5=Frontal Delaunay, 6=Frontal Hex, 7=MMG3D, 9=R-tree) (Default=1) +Mesh.Recombine3DAll = 0; + +Mesh.Optimize = 1; +Mesh.OptimizeNetgen = 1; + +Mesh.Smoothing = 0; + +Merge <>; +Merge <>; +Merge <>; + +CreateTopology; + +ll[] = Line "*"; +L_LV_base = newl; Compound Line(L_LV_base) = ll[2]; +L_RV_base = newl; Compound Line(L_RV_base) = ll[0]; +L_epi_base = newl; Compound Line(L_epi_base) = ll[1]; +// Physical Line("EPI_BASE") = {L_epi_base}; +//Physical Line(0) = {L_epi_base}; + +ss[] = Surface "*"; +S_LV = news; Compound Surface(S_LV) = ss[0]; +S_RV = news; Compound Surface(S_RV) = ss[1]; +S_epi = news; Compound Surface(S_epi) = ss[2]; +// Physical Surface("LV") = {S_LV}; +// Physical Surface("RV") = {S_RV}; +// Physical Surface("epi") = {S_epi}; +//Physical Surface(3) = {S_epi}; +//Physical Surface(1) = {S_RV}; +//Physical Surface(2) = {S_LV}; + + +LL_base = newll; Line Loop(LL_base) = {L_LV_base, L_RV_base, L_epi_base}; +S_base = news; Plane Surface(S_base) = {LL_base}; +// Physical Surface("BASE") = {S_base}; +//Physical Surface(4) = {S_base}; + +SL_wall = newsl; Surface Loop(SL_wall) = {S_LV, S_RV, S_epi, S_base}; +V_wall = newv; Volume(V_wall) = {SL_wall}; +//Physical Volume("WALL") = {V_wall}; +Physical Volume(0) = {V_wall}; + diff --git a/vtk_py/CreateVertexFromPoint.py b/vtk_py/CreateVertexFromPoint.py new file mode 100644 index 0000000..720adcb --- /dev/null +++ b/vtk_py/CreateVertexFromPoint.py @@ -0,0 +1,19 @@ +######################################################################## + +import sys +import vtk + +######################################################################## + +def CreateVertexFromPoint(ugrid): + + vertices = vtk.vtkCellArray() + for p in range(ugrid.GetNumberOfPoints()): + vert = vtk.vtkVertex() + vert.GetPointIds().SetId(0, p) + vertices.InsertNextCell(vert) + + ugrid.SetCells(1, vertices) + + + diff --git a/vtk_py/CreateVertexFromPoint.pyc b/vtk_py/CreateVertexFromPoint.pyc new file mode 100644 index 0000000..eeac6d7 Binary files /dev/null and b/vtk_py/CreateVertexFromPoint.pyc differ diff --git a/vtk_py/LV.geo b/vtk_py/LV.geo new file mode 100644 index 0000000..1ed44fc --- /dev/null +++ b/vtk_py/LV.geo @@ -0,0 +1,74 @@ +Geometry.HideCompounds = 1; + +Mesh.CharacteristicLengthFactor = <>; // Coarse + +Mesh.Algorithm = 6; // (1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=bamg, 8=delquad) (Default=2) +Mesh.RecombineAll = 0; + +Mesh.RemeshAlgorithm = 1; // (0=no split, 1=automatic, 2=automatic only with metis) (Default=0) + +Mesh.RemeshParametrization = 7; // (0=harmonic_circle, 1=conformal_spectral, 2=rbf, 3=harmonic_plane, 4=convex_circle, 5=convex_plane, 6=harmonic square, 7=conformal_fe) (Default=4) + +Mesh.Algorithm3D = 4; // (1=Delaunay, 4=Frontal, 5=Frontal Delaunay, 6=Frontal Hex, 7=MMG3D, 9=R-tree) (Default=1) +Mesh.Recombine3DAll = 0; + +Mesh.Optimize = 1; +Mesh.OptimizeNetgen = 1; + +Mesh.Smoothing = 0; + +Merge "<>"; +Merge "<>"; + +CreateTopology; + +ll[] = Line "*"; +L_LV_base = newl; Compound Line(L_LV_base) = ll[1]; +L_epi_base = newl; Compound Line(L_epi_base) = ll[0]; +//Physical Line("EPI_BASE") = {L_epi_base}; + +ss[] = Surface "*"; +S_LV = news; Compound Surface(S_LV) = ss[0]; +S_epi = news; Compound Surface(S_epi) = ss[1]; +Physical Surface("LV") = {S_LV}; +Physical Surface("epi") = {S_epi}; + +LL_base = newll; Line Loop(LL_base) = {L_LV_base, L_epi_base}; +S_base = news; Plane Surface(S_base) = {LL_base}; +Physical Surface("BASE") = {S_base}; + +SL_wall = newsl; Surface Loop(SL_wall) = {S_LV, S_epi, S_base}; +V_wall = newv; Volume(V_wall) = {SL_wall}; +Physical Volume("WALL") = {V_wall}; + + +// +//// P1 = newp; Point(P1) = {36., 74., 70.}; +//// Field[1] = Attractor; +//// Field[1].NodesList = {P1}; +//// Field[2] = Threshold; +//// Field[2].IField = 1; +//// Field[2].LcMin = 100.; +//// Field[2].LcMax = 100.; +//// Field[2].DistMin = 0.; +//// Field[2].DistMax = 10.; +//// Background Field = 2; +// +//// Field[1] = Box; +//// Field[1].VIn = 5.; +//// Field[1].VOut = 5.; +//// Field[1].XMin = 30.; +//// Field[1].XMax = 40.; +//// Field[1].YMin = 70.; +//// Field[1].YMax = 80.; +//// Field[1].ZMin = 69.; +//// Field[1].ZMax = 71.; +//// Background Field = 1; + + + + + + + + diff --git a/vtk_py/LV_original.geo b/vtk_py/LV_original.geo new file mode 100644 index 0000000..1ed44fc --- /dev/null +++ b/vtk_py/LV_original.geo @@ -0,0 +1,74 @@ +Geometry.HideCompounds = 1; + +Mesh.CharacteristicLengthFactor = <>; // Coarse + +Mesh.Algorithm = 6; // (1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=bamg, 8=delquad) (Default=2) +Mesh.RecombineAll = 0; + +Mesh.RemeshAlgorithm = 1; // (0=no split, 1=automatic, 2=automatic only with metis) (Default=0) + +Mesh.RemeshParametrization = 7; // (0=harmonic_circle, 1=conformal_spectral, 2=rbf, 3=harmonic_plane, 4=convex_circle, 5=convex_plane, 6=harmonic square, 7=conformal_fe) (Default=4) + +Mesh.Algorithm3D = 4; // (1=Delaunay, 4=Frontal, 5=Frontal Delaunay, 6=Frontal Hex, 7=MMG3D, 9=R-tree) (Default=1) +Mesh.Recombine3DAll = 0; + +Mesh.Optimize = 1; +Mesh.OptimizeNetgen = 1; + +Mesh.Smoothing = 0; + +Merge "<>"; +Merge "<>"; + +CreateTopology; + +ll[] = Line "*"; +L_LV_base = newl; Compound Line(L_LV_base) = ll[1]; +L_epi_base = newl; Compound Line(L_epi_base) = ll[0]; +//Physical Line("EPI_BASE") = {L_epi_base}; + +ss[] = Surface "*"; +S_LV = news; Compound Surface(S_LV) = ss[0]; +S_epi = news; Compound Surface(S_epi) = ss[1]; +Physical Surface("LV") = {S_LV}; +Physical Surface("epi") = {S_epi}; + +LL_base = newll; Line Loop(LL_base) = {L_LV_base, L_epi_base}; +S_base = news; Plane Surface(S_base) = {LL_base}; +Physical Surface("BASE") = {S_base}; + +SL_wall = newsl; Surface Loop(SL_wall) = {S_LV, S_epi, S_base}; +V_wall = newv; Volume(V_wall) = {SL_wall}; +Physical Volume("WALL") = {V_wall}; + + +// +//// P1 = newp; Point(P1) = {36., 74., 70.}; +//// Field[1] = Attractor; +//// Field[1].NodesList = {P1}; +//// Field[2] = Threshold; +//// Field[2].IField = 1; +//// Field[2].LcMin = 100.; +//// Field[2].LcMax = 100.; +//// Field[2].DistMin = 0.; +//// Field[2].DistMax = 10.; +//// Background Field = 2; +// +//// Field[1] = Box; +//// Field[1].VIn = 5.; +//// Field[1].VOut = 5.; +//// Field[1].XMin = 30.; +//// Field[1].XMax = 40.; +//// Field[1].YMin = 70.; +//// Field[1].YMax = 80.; +//// Field[1].ZMin = 69.; +//// Field[1].ZMax = 71.; +//// Background Field = 1; + + + + + + + + diff --git a/vtk_py/Set4ChamberDirection.py b/vtk_py/Set4ChamberDirection.py new file mode 100644 index 0000000..1396b23 --- /dev/null +++ b/vtk_py/Set4ChamberDirection.py @@ -0,0 +1,62 @@ +######################################################################## +import argparse +import numpy as np +from dolfin import * +import math +######################################################################## + + +def Set4ChamberDirection(mesh, outfilename, apexC, apexR, basalC, basalN, outdirectory="./"): + + + def BCbase(x, on_boundary): + basalNorm = np.linalg.norm(basalN) + basalNN = 1.0/basalNorm*np.array(basalN) + + return (x[0] - basalC[0])*basalNN[0] + (x[1] - basalC[1])*basalNN[1] < DOLFIN_EPS and on_boundary + + def BCapex(x, on_boundary): + return (x[0] - apexC[0])**2 + (x[1] - apexC[1])**2 < apexR[0]**2 and on_boundary + + + V = FunctionSpace(mesh, 'Lagrange', 1) + u0 = Constant(1.0) + u1 = Constant(0.0) + + bc =[DirichletBC(V, u1, BCapex), DirichletBC(V, u0, BCbase)] + + # Define variational problem + u = TrialFunction(V) + v = TestFunction(V) + f = Constant(0) + a = inner(nabla_grad(u), nabla_grad(v))*dx + L = f*v*dx + + # Compute solution + u = Function(V) + solve(a == L, u, bc) + u_a = u.vector().array() + + # Compute gradient + V_g = VectorFunctionSpace(mesh, 'Lagrange', 1) + v = TestFunction(V_g) + w = TrialFunction(V_g) + + a = inner(w, v)*dx + L = inner(grad(u), v)*dx + grad_u = Function(V_g) + solve(a == L, grad_u) + #normalize_grad_u = project(grad_u/sqrt(dot(grad_u, grad_u)), V_g) + grad_u.rename('matdir', 'matdir') + + #plot(normalize_grad_u, interactive=True) + pvdoutfile = outdirectory+outfilename+"_matdir.pvd" + file15 = File(pvdoutfile) + file15 << grad_u + + #plot(normalize_grad_u, interactive=True) + pvdoutfile2 = outdirectory+outfilename+"_dirsoln.pvd" + file16 = File(pvdoutfile2) + file16 << u + + diff --git a/vtk_py/Set4ChamberDirection.pyc b/vtk_py/Set4ChamberDirection.pyc new file mode 100644 index 0000000..b713668 Binary files /dev/null and b/vtk_py/Set4ChamberDirection.pyc differ diff --git a/vtk_py/SetBiVFiber.py b/vtk_py/SetBiVFiber.py new file mode 100644 index 0000000..4d6a7f6 --- /dev/null +++ b/vtk_py/SetBiVFiber.py @@ -0,0 +1,552 @@ +######################################################################## +import argparse +import numpy as np +#from thLib import quat +import sys +import os +from dolfin import * +from sympy import Symbol, nsolve +import math +from scipy import linalg +from scipy import optimize +from cgkit.cgtypes import * +######################################################################## + + +def SetBiVFiber(mesh, boundaries, mtvfiberfilename, mtvsheetfilename, al_endo, al_epi, b_endo, b_epi, isrotatept, isreturn, outfilename, outdirectory="./", epiid=2, rvid=1, lvid=3): + + + # Set Input files + + #outdirectory = './' + #outfilename = "temp" + #filename = "/home/lclee/Research/fiber_orientation/Laplace_function_smaller_mesh/back_up/mesh/LKK_EDmesh.xml" + #facetfilename = "/home/lclee/Research/fiber_orientation/Laplace_function_smaller_mesh/back_up/mesh/LKK_EDmesh_facet_region.xml" + #print outfilename + #print mtvfiberfilename + #print isrotatept + + + # Set Fiber angle + #b_endo = -65; b_epi = 25; al_endo = 40; al_epi = -50; + al_endo = al_endo*math.pi/180; b_endo = b_endo*math.pi/180; + al_epi = al_epi*math.pi/180; b_epi = b_epi*math.pi/180; + + minz = np.amin(mesh.coordinates()[:,2]) + maxz = np.amax(mesh.coordinates()[:,2]) + + # Boundary condition for Laplace equation from the bottom to the top + + def right_boundary(x): + return x[2] < minz+1.0 + + # Function that solves the Laplace equation and and calculates the gradient of the solution + + def lap(Me, boud, par,op, filename): + epi=epiid; rv=rvid; lv=lvid; + # Create mesh and define function space + mesh = Me + V = FunctionSpace(mesh, 'Lagrange', 1) + y = mesh.coordinates() + sa = y.shape + ttt = y[:, 2].min() + cord = np.argwhere(y == ttt); + point = y[cord[0,0],:] + #print sa, cord, point + u0 = Constant(0.0) + if op == 1: + bc =[ DirichletBC(V, u0, right_boundary), DirichletBC(V, 1, boud, 4)] + # Define boundary conditions + else: + bc = [DirichletBC(V, par[0], boud, lv), DirichletBC(V, par[1], boud, epi ), DirichletBC(V, par[2], boud, rv)] + + # Define variational problem + u = TrialFunction(V) + v = TestFunction(V) + f = Constant(0) + a = inner(nabla_grad(u), nabla_grad(v))*dx + L = f*v*dx + + # Compute solution + u = Function(V) + solve(a == L, u, bc) + u_a = u.vector().array() + + # Compute gradient + V_g = VectorFunctionSpace(mesh, 'Lagrange', 1) + v = TestFunction(V_g) + w = TrialFunction(V_g) + + a = inner(w, v)*dx + L = inner(grad(u), v)*dx + grad_u = Function(V_g) + solve(a == L, grad_u) + grad_u.rename('grad_u', 'continuous gradient field') + grad_ua = grad_u.vector().array() + + #plot(u, interactive=True) + + # Dump solution to file in VTK format + #newfilename = filename + '.pvd' + #file1= File(newfilename) + #file1<< u + + #newfilename = filename + 'grad.pvd' + #file2 = File(newfilename) + #file2 << grad_u + + # Hold plot + #interactive() + return u_a, grad_ua + + # Function to calculate the lenght of the vector + + def len_vec(vec): + l = (vec[0]**2 + vec[1]**2 + vec[2]**2)**0.5 + return l + + + + ################################################################################################## + # Function to calculate the orthogonal axis using the gradients calculated in the previous step + ################################################################################################### + def L1(e0, v0): + + L1x = (v0[0] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[0])**2 + L1y = (v0[1] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[1])**2 + L1z = (v0[2] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[2])**2 + + return (L1x + L1y + L1z)**0.5; + + def P(e0, v0): + + P1x = v0[0] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[0] + P1y = v0[1] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[1] + P1z = v0[2] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[2] + + return [P1x, P1y, P1z]; + + def function_e0(e0, v0, e1): + + f = [L1(e0,v0)*e0[0] - (e1[1]*P(e0,v0)[2] - e1[2]*P(e0,v0)[1]), + L1(e0,v0)*e0[1] - (e1[2]*P(e0,v0)[0] - e1[0]*P(e0,v0)[2]), + L1(e0,v0)*e0[2] - (e1[0]*P(e0,v0)[1] - e1[1]*P(e0,v0)[0])] + + return f; + + + def axisf(vec1, vec2): + + len_vec2 = len_vec(vec2); len_vec1 = len_vec(vec1); + e1 = vec1/len_vec1; ini_e2 = vec2/len_vec2; + ini_e0 = np.cross(e1, ini_e2) + + # Solve using symbolic + #e0x = Symbol('e0x'); e0y = Symbol('e0y') ; e0z = Symbol('e0z'); e2x = Symbol('e2x'); e2y = Symbol('e2y') ; e2z = Symbol('e2z'); + + #aa = nsolve([ e0x - e1[1]*e2z + e1[2]*e2y, + # e0y - e1[2]*e2x + e1[0]*e2z, + # e0z - e1[0]*e2y + e1[1]*e2x, + # e2x*( ( vec2[0] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0x)**2 + ( vec2[1] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0y)**2 + ( vec2[2] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0z)**2 )**0.5 - vec2[0] + (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0x , + # e2y*( ( vec2[0] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0x)**2 + ( vec2[1] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0y)**2 + ( vec2[2] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0z)**2 )**0.5 - vec2[1] + (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0y, + # e2z*( ( vec2[0] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0x)**2 + ( vec2[1] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0y)**2 + ( vec2[2] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0z)**2 )**0.5 - vec2[2] + (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0z ], + # [ e0x, e0y, e0z, e2x, e2y, e2z ],[ini_e0[0], ini_e0[1], ini_e0[2], ini_e2[0], ini_e2[1],ini_e2[2] ], minimal=True) + + + e0 = np.zeros(3); e2 = np.zeros(3); + #e0[0] = aa[0]; e0[1] = aa[1]; e0[2] = aa[2]; + #e2[0] = aa[3]; e2[1] = aa[4]; e2[2] = aa[5]; + + # Solve using numerical + def function_wrap(e0): + return function_e0(e0, vec2, e1) + + sol = optimize.root(function_wrap, [ini_e0[0], ini_e0[1], ini_e0[2]], method='hybr') + e0[0] = sol.x[0]; e0[1] = sol.x[1]; e0[2] = sol.x[2]; + e2 = P(e0, vec2); + len_e2 = len_vec(e2) + e2[0] = e2[0]/len_e2; e2[1] = e2[1]/len_e2; e2[2] = e2[2]/len_e2; + + #print e0[0], e0[1], e0[2] + #print e2[0], e2[1], e2[2] + + Q = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + + + return Q + + outfile = open("quat.txt", "w") + + ################################################################################################# + #Function to ensure the that the axis are orthogonal + ################################################################################################# + def orto(Q, cnt): + e0 = np.zeros(3); e1 = np.zeros(3); e2 = np.zeros(3); + e0[0] = Q[0][0]; e0[1] = Q[1][0]; e0[2] = Q[2][0]; + e1[0] = Q[0][1]; e1[1] = Q[1][1]; e1[2] = Q[2][1]; + e2[0] = Q[0][2]; e2[1] = Q[1][2]; e2[2] = Q[2][2]; + e0x = Symbol('e0x'); e0y = Symbol('e0y') ; e0z = Symbol('e0z'); e2x = Symbol('e2x'); e2y = Symbol('e2y') ; e2z = Symbol('e2z'); + + + try: + + aa = nsolve( [ e0x - e1[1]*e2z + e1[2]*e2y, e0y - e1[2]*e2x + e1[0]*e2z, e0z - e1[0]*e2y + e1[1]*e2x, e1[0] - e2y*e0z + e2z*e0y, e1[1] - e2z*e0x + e2x*e0z, e1[2] - e2x*e0y + e2y*e0x ], [ e0x, e0y, e0z, e2x, e2y, e2z ],[e0[0], e0[1], e0[2], e2[0], e2[1],e2[2] ]) + + + + e0[0] = aa[0]; e0[1] = aa[1]; e0[2] = aa[2]; + e2[0] = aa[3]; e2[1] = aa[4]; e2[2] = aa[5]; + Qa = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + + except ZeroDivisionError as detail: + print 'Handling run-time error:', detail + Qa = Q + f = quat.rotmat2quat(Qa) + print >>outfile, cnt, " ", f + return Qa + + + def orto3(Q, cnt): + + Q2 = np.dot(np.transpose(Q),Q) + Q2inv = np.linalg.inv(Q2) + sqrtQ2 = linalg.sqrtm(Q2inv) + Qa = np.dot(Q,sqrtQ2) + + return Qa + + ################################################################################################# + #Function to ensure the that the axis are orthogonal but this one is not working prorperly + ################################################################################################# + + def orto2(Q): + e0 = np.zeros(3); e1 = np.zeros(3); e2 = np.zeros(3); + e0[0] = Q[0][0]; e0[1] = Q[1][0]; e0[2] = Q[2][0]; + e1[0] = Q[0][1]; e1[1] = Q[1][1]; e1[2] = Q[2][1]; + e2[0] = Q[0][2]; e2[1] = Q[1][2]; e2[2] = Q[2][2]; + + while np.dot(e0, e1) + np.dot(e0, e2) + np.dot(e1, e2) > 10e-30: + e2 = np.cross(e0, e1); + e0 = np.cross(e1, e2); + Qa = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + return Qa + + ############################################################################################## + #Function 3 - This function rotates the axis calculated in the previous steps + ############################################################################################## + + def orient(Q, al, bt): + arr1 =np.array( [[np.cos(al), -np.sin(al), 0 ],[np.sin(al), np.cos(al), 0],[0, 0, 1]]); + arr2 = np.array([[1, 0, 0],[0, np.cos(bt), np.sin(bt) ],[0, -np.sin(bt), np.cos(bt) ]]); + out = np.dot(Q, arr1, arr2) + return out + + ################################################################################################## + #Function 4 - This function calculates quarternions and interpolates these quarternions + ################################################################################################# + + + def bislerp(Qa, Qb, t): + + Qa_M = mat3([Qa[0,0], Qa[0,1], Qa[0,2], Qa[1,0], Qa[1,1], Qa[1,2], Qa[2,0], Qa[2,1], Qa[2,2]]) + Qb_M = mat3([Qb[0,0], Qb[0,1], Qb[0,2], Qb[1,0], Qb[1,1], Qb[1,2], Qb[2,0], Qb[2,1], Qb[2,2]]) + qa = quat(Qa_M) + qb = quat(Qb_M) + + val = np.zeros(8) + quat_i = quat(0,1,0,0) + quat_j = quat(0,0,1,0) + quat_k = quat(0,0,0,1) + quat_array = [qa, -qa, qa*quat_i, -qa*quat_i, qa*quat_j, -qa*quat_j, qa*quat_k, -qa*quat_k] + cnt = 0 + for qt in quat_array: + val[cnt] = qt.dot(qb) + cnt = cnt + 1 + + qt = quat_array[val.argmax(axis=0)] + + if(t < 0): + t = 0.0 + + + qm = slerp(t, qt, qb) + qm = qm.normalize() + Qm_M = qm.toMat3() + Qm = [[Qm_M[0,0], Qm_M[0,1], Qm_M[0,2]], [Qm_M[1,0], Qm_M[1,1], Qm_M[1,2]], [Qm_M[2,0], Qm_M[2,1], Qm_M[2,2]]] + + return Qm + + + + ################################################################################################# + ######Generating results and using the functions ########## + ################################################################################################# + # DOF map + V = VectorFunctionSpace(mesh, "Lagrange", 1) + S = FunctionSpace(mesh, "Lagrange", 1) + + dof_coordinates = V.tabulate_dof_coordinates() + Sdof_coordinates = S.tabulate_dof_coordinates() + n = V.dim() + d = mesh.geometry().dim() + dof_coordinates.resize((n, d)) + Sdof_coordinates.resize((n,d)) + + x_dofs = V.sub(0).dofmap().dofs() + y_dofs = V.sub(1).dofmap().dofs() + z_dofs = V.sub(2).dofmap().dofs() + + jj = np.array([ 1, 1, 1] ); hh = np.array([1, 1, 1]); print np.dot(jj, hh) + + + ####### Solving the poisson equation ############ + + # case 1) epi -> u = 0 and rv/lv -> u = 1 + + print "Solve Poisson Eq. 1, epi -> u = 0 and rv/lv -> u = 1" + par1 = [0, 1, 0]; epi, dd = lap(mesh, boundaries, par1, 0, 'phi_epi') + + num_of_nodes = len(dd)/3 + scalar_array = np.zeros(num_of_nodes) + scalar_dof = S.dofmap().dofs() + + # case 2) lv -> u = 0 and rv/epi -> u = 1 + + print "Solve Poisson Eq. 2, lv -> u = 0 and rv/epi -> u = 1" + par2 = [1, 0, 0]; lv, dd2 = lap(mesh, boundaries, par2, 0, 'phi_lv'); #dd2 = -1*dd2 + + # case 3) rv -> u = 0 and epi/lv -> u = 1 + + print "Solve Poisson Eq. 3, rv -> u = 0 and epi/lv -> u = 1" + par3 = [0, 0, 1]; rv, dd3 = lap(mesh, boundaries, par3, 0, 'phi_rv') + + #case 4) from the top to the bottom + + print "Solve Poisson Eq. 4, from the top to the bottom" + par1 = [0, 1, 0]; b, dd4 = lap(mesh, boundaries, par1, 1, 'phi_ab') + + + # Start calculating the fiber orientation + cnt = 0; c = 0; + vector_array = np.zeros(V.dim()) + func_of_vector = Function(V); + func_of_scalar = Function(S); + func_of_e1 = Function(V); + func_of_e2 = Function(V); + func_of_e3 = Function(V); + + vec_dd = np.zeros(3); vec_dd2 = np.zeros(3); vec_dd3 = np.zeros(3); vec_dd4 = np.zeros(3); + + Qepi = np.zeros((len(dd),3)); Qrv = np.zeros((len(dd),3)); Qlv = np.zeros((len(dd),3)); + Qendo = np.zeros((len(dd),3)) + Qfiber = np.zeros((len(dd),3)) + + e0_epi = np.zeros(len(dd)); e1_epi = np.zeros(len(dd)); e2_epi = np.zeros(len(dd)); + e0_rv = np.zeros(len(dd)); e1_rv = np.zeros(len(dd)); e2_rv = np.zeros(len(dd)); + e0_lv = np.zeros(len(dd)); e1_lv = np.zeros(len(dd)); e2_lv = np.zeros(len(dd)); + check = np.zeros(len(dd)); check2 = np.zeros(len(dd)); + ds = np.zeros(len(dd)/3); al_s = np.zeros(len(dd)/3); b_s = np.zeros(len(dd)/3); + al_w = np.zeros(len(dd)/3); b_w = np.zeros(len(dd)/3); + + e0_endo = np.zeros(len(dd)); e1_endo = np.zeros(len(dd)); e2_endo = np.zeros(len(dd)); + e0_fiber = np.zeros(len(dd)); e1_fiber = np.zeros(len(dd)); e2_fiber = np.zeros(len(dd)); + + + # Open MTV fiber and sheet files + if(mtvfiberfilename): + mtvfiberfile = open(mtvfiberfilename, 'w') + print >>mtvfiberfile, len(dd)/3, 10 + + + if(mtvsheetfilename): + mtvsheetfile = open(mtvsheetfilename, 'w') + print >>mtvsheetfile, len(dd)/3 + + + num = 1 + #for x_dof, y_dof, z_dof, scl in zip(x_dofs[num:num+2], y_dofs[num:num+2], z_dofs[num:num+2], scalar_dof[num:num+2]): + for x_dof, y_dof, z_dof, scl in zip(x_dofs, y_dofs, z_dofs, scalar_dof): + + #print "cnt = ", cnt + + if(abs(rv[scl]) < 1e-9 and abs(rv[scl] + lv[scl]) < 1e-9): + ds[scl] = 0.0 + else: + ds[scl] = rv[scl]/(lv[scl]+rv[scl]) + + al_s[scl] = al_endo*(1 - ds[scl]) - al_endo*ds[scl]; b_s[scl] = b_endo*(1 - ds[scl]) - b_endo*ds[scl]; + al_w[scl] = al_endo*(1 - epi[scl]) + al_epi*epi[scl]; b_w[scl] = b_endo*(1 - epi[scl]) + b_epi*epi[scl]; + + vec_dd[0] = dd[x_dof]; vec_dd[1] = dd[y_dof]; vec_dd[2] = dd[z_dof]; + vec_dd2[0] = dd2[x_dof]; vec_dd2[1] = dd2[y_dof]; vec_dd2[2] = dd2[z_dof]; + vec_dd3[0] = dd3[x_dof]; vec_dd3[1] = dd3[y_dof]; vec_dd3[2] = dd3[z_dof]; + vec_dd4[0] = dd4[x_dof]; vec_dd4[1] = dd4[y_dof]; vec_dd4[2] = dd4[z_dof]; + + + Qlv[c:c+3][0:3]= axisf(vec_dd4, -1.0*vec_dd2); + Qlv[c:c+3][0:3] = orto3(Qlv[c:c+3][0:3], cnt); + Qlv[c:c+3][0:3]= orient(Qlv[c:c+3][0:3], al_s[scl], b_s[scl]) + + + e0_lv[x_dof] = Qlv[c][0]; e0_lv[y_dof] = Qlv[c+1][0]; e0_lv[z_dof] = Qlv[c+2][0]; + e1_lv[x_dof] = Qlv[c][1]; e1_lv[y_dof] = Qlv[c+1][1]; e1_lv[z_dof] = Qlv[c+2][1]; + e2_lv[x_dof] = Qlv[c][2]; e2_lv[y_dof] = Qlv[c+1][2]; e2_lv[z_dof] = Qlv[c+2][2]; + + Qrv[c:c+3][0:3] = axisf(vec_dd4, -1.0*vec_dd3); + Qrv[c:c+3][0:3] = orto3(Qrv[c:c+3][0:3], cnt); + Qrv[c:c+3][0:3]= orient(Qrv[c:c+3][0:3], -al_s[scl], -b_s[scl]); + + e0_rv[x_dof] = Qrv[c][0]; e0_rv[y_dof] = Qrv[c+1][0]; e0_rv[z_dof] = Qrv[c+2][0]; + e1_rv[x_dof] = Qrv[c][1]; e1_rv[y_dof] = Qrv[c+1][1]; e1_rv[z_dof] = Qrv[c+2][1]; + e2_rv[x_dof] = Qrv[c][2]; e2_rv[y_dof] = Qrv[c+1][2]; e2_rv[z_dof] = Qrv[c+2][2]; + + + Qendo[c:c+3][0:3] = bislerp(Qlv[c:c+3][0:3], Qrv[c:c+3][0:3], ds[scl]) + e0_endo[x_dof] = Qendo[c][0]; e0_endo[y_dof] = Qendo[c+1][0]; e0_endo[z_dof] = Qendo[c+2][0]; + e1_endo[x_dof] = Qendo[c][1]; e1_endo[y_dof] = Qendo[c+1][1]; e1_endo[z_dof] = Qendo[c+2][1]; + e2_endo[x_dof] = Qendo[c][2]; e2_endo[y_dof] = Qendo[c+1][2]; e2_endo[z_dof] = Qendo[c+2][2]; + + + Qepi[c:c+3][0:3] = axisf(vec_dd4, vec_dd); + Qepi[c:c+3][0:3] = orto3(Qepi[c:c+3][0:3], cnt); + Qepi[c:c+3][0:3] = orient(Qepi[c:c+3][0:3], al_w[scl], b_w[scl]); + + e0_epi[x_dof] = Qepi[c][0]; e0_epi[y_dof] = Qepi[c+1][0]; e0_epi[z_dof] = Qepi[c+2][0]; + e1_epi[x_dof] = Qepi[c][1]; e1_epi[y_dof] = Qepi[c+1][1]; e1_epi[z_dof] = Qepi[c+2][1]; + e2_epi[x_dof] = Qepi[c][2]; e2_epi[y_dof] = Qepi[c+1][2]; e2_epi[z_dof] = Qepi[c+2][2]; + + Qfiber[c:c+3][0:3] = bislerp(Qendo[c:c+3][0:3], Qepi[c:c+3][0:3], epi[scl]) + e0_fiber[x_dof] = Qfiber[c][0]; e0_fiber[y_dof] = Qfiber[c+1][0]; e0_fiber[z_dof] = Qfiber[c+2][0]; + e1_fiber[x_dof] = Qfiber[c][1]; e1_fiber[y_dof] = Qfiber[c+1][1]; e1_fiber[z_dof] = Qfiber[c+2][1]; + e2_fiber[x_dof] = Qfiber[c][2]; e2_fiber[y_dof] = Qfiber[c+1][2]; e2_fiber[z_dof] = Qfiber[c+2][2]; + + + cnt = cnt + 1; + c = c + 3; + + if(isrotatept): + points = [(-Sdof_coordinates[scl][2]+maxz)/10.0, Sdof_coordinates[scl][1]/10.0, Sdof_coordinates[scl][0]/10.0] + fvectors = [-1.0*e0_fiber[z_dof], e0_fiber[y_dof], e0_fiber[x_dof]] + svectors = [-1.0*e2_fiber[z_dof], e2_fiber[y_dof], e2_fiber[x_dof]] + + else: + points = [Sdof_coordinates[scl][0], Sdof_coordinates[scl][1], Sdof_coordinates[scl][2]] + fvectors = [e0_fiber[x_dof], e0_fiber[y_dof], e0_fiber[z_dof]] + svectors = [e2_fiber[x_dof], e2_fiber[y_dof], e2_fiber[z_dof]] + + + print >>mtvfiberfile, points[0], points[1], points[2], fvectors[0], fvectors[1], fvectors[2] + print >>mtvsheetfile, points[0], points[1], points[2], svectors[0], svectors[1], svectors[2] + + + + + + #func_of_vector.vector()[:] = e0_epi + #file1 = File("e0_epi.pvd") + #file1 << func_of_vector + # + #func_of_vector.vector()[:] = e1_epi + #file2 = File("e1_epi.pvd") + #file2 << func_of_vector + # + #func_of_vector.vector()[:] = e2_epi + #file3 = File("e2_epi.pvd") + #file3 << func_of_vector + # + #func_of_vector.vector()[:] = e0_rv + #file4 = File("e0_rv.pvd") + #file4 << func_of_vector + # + #func_of_vector.vector()[:] = e1_rv + #file5 = File("e1_rv.pvd") + #file5 << func_of_vector + # + #func_of_vector.vector()[:] = e2_rv + #file6 = File("e2_rv.pvd") + #file6 << func_of_vector + # + #func_of_vector.vector()[:] = e0_lv + #file7 = File("e0_lv.pvd") + #file7 << func_of_vector + # + #func_of_vector.vector()[:] = e1_lv + #file8 = File("e1_lv.pvd") + #file8 << func_of_vector + # + #func_of_vector.vector()[:] = e2_lv + #file9 = File("e2_lv.pvd") + #file9 << func_of_vector + # + #func_of_vector.vector()[:] = e0_endo + #file10 = File("e0_endo.pvd") + #file10 << func_of_vector + # + #func_of_vector.vector()[:] = e1_endo + #file11 = File("e1_endo.pvd") + #file11 << func_of_vector + # + #func_of_vector.vector()[:] = e2_endo + #file12 = File("e2_endo.pvd") + #file12 << func_of_vector + + pvdoutfile = outdirectory+outfilename+"_e0_fiber.pvd" + func_of_e1.vector()[:] = e0_fiber + func_of_e1.rename("fiber", "fiber") + file13 = File(pvdoutfile) + file13 << func_of_e1 + + pvdoutfile = outdirectory+outfilename+"_e1_fiber.pvd" + func_of_e2.vector()[:] = e1_fiber + func_of_e2.rename("sheet", "sheet") + file14 = File(pvdoutfile) + file14 << func_of_e2 + + pvdoutfile = outdirectory+outfilename+"_e2_fiber.pvd" + func_of_e3.rename("sheetnormal", "sheetnormal") + func_of_e3.vector()[:] = e2_fiber + file15 = File(pvdoutfile) + file15 << func_of_e3 + + print isrotatept + print outdirectory + outfilename + print "*******************************************************" + + if(isreturn): + + return func_of_e1, func_of_e2, func_of_e3 + +if (__name__ == "__main__"): + + parser = argparse.ArgumentParser() + parser.add_argument('--xml_folder', type=str, required=True) + parser.add_argument('--xml_meshfilename', type=str, required=True) + parser.add_argument('--xml_facetfilename', type=str, required=True) + parser.add_argument('--mtv_grid_directory', type=str, required=True) + parser.add_argument('--mtv_basename', type=str, required=True) + parser.add_argument('--isrotatept', type=bool, required=True) + parser.add_argument('--al_endo', type=float, required=True) + parser.add_argument('--al_epi', type=float, required=True) + parser.add_argument('--b_endo', type=float, required=True) + parser.add_argument('--b_epi', type=float, required=True) + args = parser.parse_args() + + print "************* Entering SetBiVFiber.py *****************" + + xmlmeshfilename = os.path.join(args.xml_folder, args.xml_meshfilename) + xmlfacetfilename = os.path.join(args.xml_folder, args.xml_facetfilename) + outdirectory = args.mtv_grid_directory + outfilename = args.mtv_basename + isrotatept = args.isrotatept + al_endo = args.al_endo + al_epi = args.al_epi + b_endo = args.b_endo + b_epi = args.b_epi + + mesh = Mesh(xmlmeshfilename) + boundaries = MeshFunction("size_t", mesh, xmlfacetfilename) + mtvfiberfilename = outdirectory+outfilename+"_fiber_rotated.axis" + mtvsheetfilename = outdirectory+outfilename+"_sheet_rotated.axis" + + SetBiVFiber(mesh, boundaries, mtvfiberfilename, mtvsheetfilename, al_endo, al_epi, b_endo, b_epi, isrotatept, outfilename, outdirectory) + diff --git a/vtk_py/SetBiVFiber_J.py b/vtk_py/SetBiVFiber_J.py new file mode 100644 index 0000000..fa82256 --- /dev/null +++ b/vtk_py/SetBiVFiber_J.py @@ -0,0 +1,675 @@ +######################################################################## +import argparse +import numpy as np +#from thLib import quat +import sys +import os +from dolfin import * +from sympy import Symbol, nsolve +import math +from scipy import linalg +from scipy import optimize + +import pdb + +#from cgkit.cgtypes import * # jaY change was this +#from cgkit import * # jaY change + +import pyquaternion as pyq +#import numpy as np + +######################################################################## + + +def SetBiVFiber_J(mesh, boundaries, mtvfiberfilename, mtvsheetfilename, al_endo, al_epi, b_endo, b_epi, isrotatept, isreturn, outfilename, outdirectory="./", epiid=2, rvid=1, lvid=3): + ''' + What: This function uses pyquaternion lib instead of cgkit for quarternion calculations + What more: pip install (http://kieranwynn.github.io/pyquaternion/) + + Where: my_bislerp() instead of bislerp() in SetBiVFiber + + How: vtk_py.SetBiVFiber_J( ... ) + + Plaussible issues: matrix to quaternion is not unique, topology is trickier + http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/tim.htm + http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ + + What else: comment out all other problematic lines + for eg., Sdof_coordinates + + + ''' + + # Set Input files + + #outdirectory = './' + #outfilename = "temp" + #filename = "/home/lclee/Research/fiber_orientation/Laplace_function_smaller_mesh/back_up/mesh/LKK_EDmesh.xml" + #facetfilename = "/home/lclee/Research/fiber_orientation/Laplace_function_smaller_mesh/back_up/mesh/LKK_EDmesh_facet_region.xml" + #print outfilename + #print mtvfiberfilename + #print isrotatept + + + # Set Fiber angle + #b_endo = -65; b_epi = 25; al_endo = 40; al_epi = -50; + al_endo = al_endo*math.pi/180; b_endo = b_endo*math.pi/180; + al_epi = al_epi*math.pi/180; b_epi = b_epi*math.pi/180; + + minz = np.amin(mesh.coordinates()[:,2]) + maxz = np.amax(mesh.coordinates()[:,2]) + + # Boundary condition for Laplace equation from the bottom to the top + + def right_boundary(x): + return x[2] < minz+1.0 + + # Function that solves the Laplace equation and and calculates the gradient of the solution + + def lap(Me, boud, par,op, filename): + epi=epiid; rv=rvid; lv=lvid; + # Create mesh and define function space + mesh = Me + V = FunctionSpace(mesh, 'Lagrange', 1) + y = mesh.coordinates() + sa = y.shape + ttt = y[:, 2].min() + cord = np.argwhere(y == ttt); + point = y[cord[0,0],:] + #print sa, cord, point + u0 = Constant(0.0) + if op == 1: + bc =[ DirichletBC(V, u0, right_boundary), DirichletBC(V, 1, boud, 4)] + # Define boundary conditions + else: + bc = [DirichletBC(V, par[0], boud, lv), DirichletBC(V, par[1], boud, epi ), DirichletBC(V, par[2], boud, rv)] + + # Define variational problem + u = TrialFunction(V) + v = TestFunction(V) + f = Constant(0) + a = inner(nabla_grad(u), nabla_grad(v))*dx + L = f*v*dx + + # Compute solution + u = Function(V) + solve(a == L, u, bc) + u_a = u.vector().array() + + # Compute gradient + V_g = VectorFunctionSpace(mesh, 'Lagrange', 1) + v = TestFunction(V_g) + w = TrialFunction(V_g) + + a = inner(w, v)*dx + L = inner(grad(u), v)*dx + grad_u = Function(V_g) + solve(a == L, grad_u) + grad_u.rename('grad_u', 'continuous gradient field') + grad_ua = grad_u.vector().array() + + #plot(u, interactive=True) + + # Dump solution to file in VTK format + #newfilename = filename + '.pvd' + #file1= File(newfilename) + #file1<< u + + #newfilename = filename + 'grad.pvd' + #file2 = File(newfilename) + #file2 << grad_u + + # Hold plot + #interactive() + return u_a, grad_ua + + # Function to calculate the lenght of the vector + + def len_vec(vec): + l = (vec[0]**2 + vec[1]**2 + vec[2]**2)**0.5 + return l + + + + ################################################################################################## + # Function to calculate the orthogonal axis using the gradients calculated in the previous step + ################################################################################################### + def L1(e0, v0): + + L1x = (v0[0] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[0])**2 + L1y = (v0[1] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[1])**2 + L1z = (v0[2] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[2])**2 + + return (L1x + L1y + L1z)**0.5; + + def P(e0, v0): + + P1x = v0[0] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[0] + P1y = v0[1] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[1] + P1z = v0[2] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[2] + + return [P1x, P1y, P1z]; + + def function_e0(e0, v0, e1): + + f = [L1(e0,v0)*e0[0] - (e1[1]*P(e0,v0)[2] - e1[2]*P(e0,v0)[1]), + L1(e0,v0)*e0[1] - (e1[2]*P(e0,v0)[0] - e1[0]*P(e0,v0)[2]), + L1(e0,v0)*e0[2] - (e1[0]*P(e0,v0)[1] - e1[1]*P(e0,v0)[0])] + + return f; + + + def axisf(vec1, vec2): + + len_vec2 = len_vec(vec2); len_vec1 = len_vec(vec1); + e1 = vec1/len_vec1; ini_e2 = vec2/len_vec2; + ini_e0 = np.cross(e1, ini_e2) + + # Solve using symbolic + #e0x = Symbol('e0x'); e0y = Symbol('e0y') ; e0z = Symbol('e0z'); e2x = Symbol('e2x'); e2y = Symbol('e2y') ; e2z = Symbol('e2z'); + + #aa = nsolve([ e0x - e1[1]*e2z + e1[2]*e2y, + # e0y - e1[2]*e2x + e1[0]*e2z, + # e0z - e1[0]*e2y + e1[1]*e2x, + # e2x*( ( vec2[0] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0x)**2 + ( vec2[1] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0y)**2 + ( vec2[2] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0z)**2 )**0.5 - vec2[0] + (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0x , + # e2y*( ( vec2[0] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0x)**2 + ( vec2[1] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0y)**2 + ( vec2[2] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0z)**2 )**0.5 - vec2[1] + (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0y, + # e2z*( ( vec2[0] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0x)**2 + ( vec2[1] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0y)**2 + ( vec2[2] - (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0z)**2 )**0.5 - vec2[2] + (e0x*vec2[0] + e0y*vec2[1] + e0z*vec2[2])*e0z ], + # [ e0x, e0y, e0z, e2x, e2y, e2z ],[ini_e0[0], ini_e0[1], ini_e0[2], ini_e2[0], ini_e2[1],ini_e2[2] ], minimal=True) + + + e0 = np.zeros(3); e2 = np.zeros(3); + #e0[0] = aa[0]; e0[1] = aa[1]; e0[2] = aa[2]; + #e2[0] = aa[3]; e2[1] = aa[4]; e2[2] = aa[5]; + + # Solve using numerical + def function_wrap(e0): + return function_e0(e0, vec2, e1) + + sol = optimize.root(function_wrap, [ini_e0[0], ini_e0[1], ini_e0[2]], method='hybr') + e0[0] = sol.x[0]; e0[1] = sol.x[1]; e0[2] = sol.x[2]; + e2 = P(e0, vec2); + len_e2 = len_vec(e2) + e2[0] = e2[0]/len_e2; e2[1] = e2[1]/len_e2; e2[2] = e2[2]/len_e2; + + #print e0[0], e0[1], e0[2] + #print e2[0], e2[1], e2[2] + + Q = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + + + return Q + + outfile = open("quat.txt", "w") + + ################################################################################################# + #Function to ensure the that the axis are orthogonal + ################################################################################################# + def orto(Q, cnt): + e0 = np.zeros(3); e1 = np.zeros(3); e2 = np.zeros(3); + e0[0] = Q[0][0]; e0[1] = Q[1][0]; e0[2] = Q[2][0]; + e1[0] = Q[0][1]; e1[1] = Q[1][1]; e1[2] = Q[2][1]; + e2[0] = Q[0][2]; e2[1] = Q[1][2]; e2[2] = Q[2][2]; + e0x = Symbol('e0x'); e0y = Symbol('e0y') ; e0z = Symbol('e0z'); e2x = Symbol('e2x'); e2y = Symbol('e2y') ; e2z = Symbol('e2z'); + + + try: + + aa = nsolve( [ e0x - e1[1]*e2z + e1[2]*e2y, e0y - e1[2]*e2x + e1[0]*e2z, e0z - e1[0]*e2y + e1[1]*e2x, e1[0] - e2y*e0z + e2z*e0y, e1[1] - e2z*e0x + e2x*e0z, e1[2] - e2x*e0y + e2y*e0x ], [ e0x, e0y, e0z, e2x, e2y, e2z ],[e0[0], e0[1], e0[2], e2[0], e2[1],e2[2] ]) + + + + e0[0] = aa[0]; e0[1] = aa[1]; e0[2] = aa[2]; + e2[0] = aa[3]; e2[1] = aa[4]; e2[2] = aa[5]; + Qa = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + + except ZeroDivisionError as detail: + print 'Handling run-time error:', detail + Qa = Q + f = quat.rotmat2quat(Qa) + print >>outfile, cnt, " ", f + return Qa + + + def orto3(Q, cnt): + + Q2 = np.dot(np.transpose(Q),Q) + Q2inv = np.linalg.inv(Q2) + sqrtQ2 = linalg.sqrtm(Q2inv) + Qa = np.dot(Q,sqrtQ2) + + return Qa + + ################################################################################################# + #Function to ensure the that the axis are orthogonal but this one is not working prorperly + ################################################################################################# + + def orto2(Q): + e0 = np.zeros(3); e1 = np.zeros(3); e2 = np.zeros(3); + e0[0] = Q[0][0]; e0[1] = Q[1][0]; e0[2] = Q[2][0]; + e1[0] = Q[0][1]; e1[1] = Q[1][1]; e1[2] = Q[2][1]; + e2[0] = Q[0][2]; e2[1] = Q[1][2]; e2[2] = Q[2][2]; + + while np.dot(e0, e1) + np.dot(e0, e2) + np.dot(e1, e2) > 10e-30: + e2 = np.cross(e0, e1); + e0 = np.cross(e1, e2); + Qa = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + return Qa + + ############################################################################################## + #Function 3 - This function rotates the axis calculated in the previous steps + ############################################################################################## + + def orient(Q, al, bt): + arr1 =np.array( [[np.cos(al), -np.sin(al), 0 ],[np.sin(al), np.cos(al), 0],[0, 0, 1]]); + arr2 = np.array([[1, 0, 0],[0, np.cos(bt), np.sin(bt) ],[0, -np.sin(bt), np.cos(bt) ]]); + out = np.dot(Q, arr1, arr2) + return out + + ################################################################################################## + #Function 4 - This function calculates quarternions and interpolates these quarternions + ################################################################################################# + + + def bislerp(Qa, Qb, t): + + Qa_M = mat3([Qa[0,0], Qa[0,1], Qa[0,2], Qa[1,0], Qa[1,1], Qa[1,2], Qa[2,0], Qa[2,1], Qa[2,2]]) + Qb_M = mat3([Qb[0,0], Qb[0,1], Qb[0,2], Qb[1,0], Qb[1,1], Qb[1,2], Qb[2,0], Qb[2,1], Qb[2,2]]) + qa = quat(Qa_M) + qb = quat(Qb_M) + + val = np.zeros(8) + quat_i = quat(0,1,0,0) + quat_j = quat(0,0,1,0) + quat_k = quat(0,0,0,1) + quat_array = [qa, -qa, qa*quat_i, -qa*quat_i, qa*quat_j, -qa*quat_j, qa*quat_k, -qa*quat_k] + cnt = 0 + for qt in quat_array: + val[cnt] = qt.dot(qb) + cnt = cnt + 1 + + qt = quat_array[val.argmax(axis=0)] + + if(t < 0): + t = 0.0 + + + qm = slerp(t, qt, qb) + qm = qm.normalize() + Qm_M = qm.toMat3() + Qm = [[Qm_M[0,0], Qm_M[0,1], Qm_M[0,2]], [Qm_M[1,0], Qm_M[1,1], Qm_M[1,2]], [Qm_M[2,0], Qm_M[2,1], Qm_M[2,2]]] + + return Qm + + + def my_bislerp(Qa, Qb, t): + + #Qa_M = mat3([Qa[0,0], Qa[0,1], Qa[0,2], Qa[1,0], Qa[1,1], Qa[1,2], Qa[2,0], Qa[2,1], Qa[2,2]]) + #Qb_M = mat3([Qb[0,0], Qb[0,1], Qb[0,2], Qb[1,0], Qb[1,1], Qb[1,2], Qb[2,0], Qb[2,1], Qb[2,2]]) + #qa = quat(Qa_M) + #qb = quat(Qb_M) + + qa = pyq.Quaternion(matrix=Qa) + qb = pyq.Quaternion(matrix=Qb) + + + val = np.zeros(8) + #quat_i = quat(0,1,0,0) + #quat_j = quat(0,0,1,0) + #quat_k = quat(0,0,0,1) + + quat_i = pyq.Quaternion(0,1,0,0) + quat_j = pyq.Quaternion(0,0,1,0) + quat_k = pyq.Quaternion(0,0,0,1) + + quat_array = [qa, -qa, qa*quat_i, -qa*quat_i, qa*quat_j, -qa*quat_j, qa*quat_k, -qa*quat_k] + + + #print('My Quarternion NUMPY array {arr}'.format(arr=np.array(qa))) + #print('My Quarternion NUMPY array {arr}'.format(arr=np.array([qa[0], qa[1], qa[2], qa[3] ]) ) ) + + + cnt = 0 + qb_arr = np.array([qb[0], qb[1], qb[2], qb[3]]) + + for qt in quat_array: + #val[cnt] = qt.dot(qb) + qt_arr = np.array([qt[0], qt[1], qt[2], qt[3]]) + val[cnt] = np.dot(qt_arr, qb_arr) + cnt = cnt + 1 + + #print('calculated val array is :{arr}'.format(arr=val)) + qt = quat_array[val.argmax(axis=0)] + #print('calculated val array is :{arr}'.format(arr=qt)) + + + if(t < 0): + t = 0.0 + + #qm = slerp(t, qt, qb) + qm = pyq.Quaternion.slerp(qt, qb, t) + qm = qm.normalised + Qm_M = qm.rotation_matrix + + #Qm = [[Qm_M[0,0], Qm_M[0,1], Qm_M[0,2]], [Qm_M[1,0], Qm_M[1,1], Qm_M[1,2]], [Qm_M[2,0], Qm_M[2,1], Qm_M[2,2]]] + #print('calculated val matrix is :{mat}'.format(mat=Qm_M)) + + return Qm_M + + + + ################################################################################################# + ######Generating results and using the functions ########## + ################################################################################################# + # DOF map + V = VectorFunctionSpace(mesh, "Lagrange", 1) + S = FunctionSpace(mesh, "Lagrange", 1) + + dof_coordinates = V.tabulate_dof_coordinates() + Sdof_coordinates = S.tabulate_dof_coordinates() + n = V.dim() + d = mesh.geometry().dim() + + #pdb.set_trace() + + dof_coordinates.resize((n, d)) + #Sdof_coordinates.resize((n,d)) # Sdof_coordinates is of size n, so not able to resize + + x_dofs = V.sub(0).dofmap().dofs() + y_dofs = V.sub(1).dofmap().dofs() + z_dofs = V.sub(2).dofmap().dofs() + + jj = np.array([ 1, 1, 1] ); hh = np.array([1, 1, 1]); print np.dot(jj, hh) + + + ####### Solving the poisson equation ############ + + # case 1) epi -> u = 0 and rv/lv -> u = 1 + #pdb.set_trace() + + print "Solve Poisson Eq. 1, epi -> u = 0 and rv/lv -> u = 1" + par1 = [0, 1, 0]; epi, dd = lap(mesh, boundaries, par1, 0, 'phi_epi') + + print "length of dd is :", len(dd) + + num_of_nodes = len(dd)/3 + scalar_array = np.zeros(num_of_nodes) + scalar_dof = S.dofmap().dofs() + + # case 2) lv -> u = 0 and rv/epi -> u = 1 + + print "Solve Poisson Eq. 2, lv -> u = 0 and rv/epi -> u = 1" + par2 = [1, 0, 0]; lv, dd2 = lap(mesh, boundaries, par2, 0, 'phi_lv'); #dd2 = -1*dd2 + + # case 3) rv -> u = 0 and epi/lv -> u = 1 + + print "Solve Poisson Eq. 3, rv -> u = 0 and epi/lv -> u = 1" + par3 = [0, 0, 1]; rv, dd3 = lap(mesh, boundaries, par3, 0, 'phi_rv') + + #case 4) from the top to the bottom + + print "Solve Poisson Eq. 4, from the top to the bottom" + par1 = [0, 1, 0]; b, dd4 = lap(mesh, boundaries, par1, 1, 'phi_ab') + + + # Start calculating the fiber orientation + cnt = 0; c = 0; + vector_array = np.zeros(V.dim()) + func_of_vector = Function(V); + func_of_scalar = Function(S); + func_of_e1 = Function(V); + func_of_e2 = Function(V); + func_of_e3 = Function(V); + + vec_dd = np.zeros(3); vec_dd2 = np.zeros(3); vec_dd3 = np.zeros(3); vec_dd4 = np.zeros(3); + + Qepi = np.zeros((len(dd),3)); Qrv = np.zeros((len(dd),3)); Qlv = np.zeros((len(dd),3)); + Qendo = np.zeros((len(dd),3)) + Qfiber = np.zeros((len(dd),3)) + + e0_epi = np.zeros(len(dd)); e1_epi = np.zeros(len(dd)); e2_epi = np.zeros(len(dd)); + e0_rv = np.zeros(len(dd)); e1_rv = np.zeros(len(dd)); e2_rv = np.zeros(len(dd)); + e0_lv = np.zeros(len(dd)); e1_lv = np.zeros(len(dd)); e2_lv = np.zeros(len(dd)); + check = np.zeros(len(dd)); check2 = np.zeros(len(dd)); + ds = np.zeros(len(dd)/3); al_s = np.zeros(len(dd)/3); b_s = np.zeros(len(dd)/3); + al_w = np.zeros(len(dd)/3); b_w = np.zeros(len(dd)/3); + + e0_endo = np.zeros(len(dd)); e1_endo = np.zeros(len(dd)); e2_endo = np.zeros(len(dd)); + e0_fiber = np.zeros(len(dd)); e1_fiber = np.zeros(len(dd)); e2_fiber = np.zeros(len(dd)); + + #pdb.set_trace() + + ''' # mtv fiber_axis and sheet files not there error + # Open MTV fiber and sheet files + if(mtvfiberfilename): + mtvfiberfile = open(mtvfiberfilename, 'w') + print >>mtvfiberfile, len(dd)/3, 10 + + + if(mtvsheetfilename): + mtvsheetfile = open(mtvsheetfilename, 'w') + print >>mtvsheetfile, len(dd)/3 + ''' + + + + num = 1 + #for x_dof, y_dof, z_dof, scl in zip(x_dofs[num:num+2], y_dofs[num:num+2], z_dofs[num:num+2], scalar_dof[num:num+2]): + for x_dof, y_dof, z_dof, scl in zip(x_dofs, y_dofs, z_dofs, scalar_dof): + + #print "cnt = ", cnt + + if(abs(rv[scl]) < 1e-9 and abs(rv[scl] + lv[scl]) < 1e-9): + ds[scl] = 0.0 + else: + ds[scl] = rv[scl]/(lv[scl]+rv[scl]) + + al_s[scl] = al_endo*(1 - ds[scl]) - al_endo*ds[scl]; b_s[scl] = b_endo*(1 - ds[scl]) - b_endo*ds[scl]; + al_w[scl] = al_endo*(1 - epi[scl]) + al_epi*epi[scl]; b_w[scl] = b_endo*(1 - epi[scl]) + b_epi*epi[scl]; + + vec_dd[0] = dd[x_dof]; vec_dd[1] = dd[y_dof]; vec_dd[2] = dd[z_dof]; + vec_dd2[0] = dd2[x_dof]; vec_dd2[1] = dd2[y_dof]; vec_dd2[2] = dd2[z_dof]; + vec_dd3[0] = dd3[x_dof]; vec_dd3[1] = dd3[y_dof]; vec_dd3[2] = dd3[z_dof]; + vec_dd4[0] = dd4[x_dof]; vec_dd4[1] = dd4[y_dof]; vec_dd4[2] = dd4[z_dof]; + + + Qlv[c:c+3][0:3]= axisf(vec_dd4, -1.0*vec_dd2); + Qlv[c:c+3][0:3] = orto3(Qlv[c:c+3][0:3], cnt); + Qlv[c:c+3][0:3]= orient(Qlv[c:c+3][0:3], al_s[scl], b_s[scl]) + + + e0_lv[x_dof] = Qlv[c][0]; e0_lv[y_dof] = Qlv[c+1][0]; e0_lv[z_dof] = Qlv[c+2][0]; + e1_lv[x_dof] = Qlv[c][1]; e1_lv[y_dof] = Qlv[c+1][1]; e1_lv[z_dof] = Qlv[c+2][1]; + e2_lv[x_dof] = Qlv[c][2]; e2_lv[y_dof] = Qlv[c+1][2]; e2_lv[z_dof] = Qlv[c+2][2]; + + Qrv[c:c+3][0:3] = axisf(vec_dd4, -1.0*vec_dd3); + Qrv[c:c+3][0:3] = orto3(Qrv[c:c+3][0:3], cnt); + Qrv[c:c+3][0:3]= orient(Qrv[c:c+3][0:3], -al_s[scl], -b_s[scl]); + + e0_rv[x_dof] = Qrv[c][0]; e0_rv[y_dof] = Qrv[c+1][0]; e0_rv[z_dof] = Qrv[c+2][0]; + e1_rv[x_dof] = Qrv[c][1]; e1_rv[y_dof] = Qrv[c+1][1]; e1_rv[z_dof] = Qrv[c+2][1]; + e2_rv[x_dof] = Qrv[c][2]; e2_rv[y_dof] = Qrv[c+1][2]; e2_rv[z_dof] = Qrv[c+2][2]; + + ''' + #Qendo[c:c+3][0:3] = bislerp(Qlv[c:c+3][0:3], Qrv[c:c+3][0:3], ds[scl]) + print Qendo[c:c+3][0:3] + print my_bislerp(Qlv[c:c+3][0:3], Qrv[c:c+3][0:3], ds[scl]) + #Qendo[c:c+3][0:3] = my_bislerp(Qlv[c:c+3][0:3], Qrv[c:c+3][0:3], ds[scl]) + print Qendo[c:c+3][0:3] + + print Qendo[c][0] + print Qendo[c][1] + print Qendo[c][2] + + print Qendo[c+1][0] + print Qendo[c+1][1] + print Qendo[c+1][2] + + print Qendo[c+2][0] + print Qendo[c+2][1] + print Qendo[c+2][2] + + print e0_endo + ''' + + #pdb.set_trace() + print "c is :", c + print "x_dof is :", x_dof + print "y_dof is :", y_dof + print "z_dof is :", z_dof + + Qendo[c:c+3][0:3] = my_bislerp(Qlv[c:c+3][0:3], Qrv[c:c+3][0:3], ds[scl]) + + e0_endo[x_dof] = Qendo[c][0]; e0_endo[y_dof] = Qendo[c+1][0]; e0_endo[z_dof] = Qendo[c+2][0]; + e1_endo[x_dof] = Qendo[c][1]; e1_endo[y_dof] = Qendo[c+1][1]; e1_endo[z_dof] = Qendo[c+2][1]; + e2_endo[x_dof] = Qendo[c][2]; e2_endo[y_dof] = Qendo[c+1][2]; e2_endo[z_dof] = Qendo[c+2][2]; + + + Qepi[c:c+3][0:3] = axisf(vec_dd4, vec_dd); + Qepi[c:c+3][0:3] = orto3(Qepi[c:c+3][0:3], cnt); + Qepi[c:c+3][0:3] = orient(Qepi[c:c+3][0:3], al_w[scl], b_w[scl]); + + e0_epi[x_dof] = Qepi[c][0]; e0_epi[y_dof] = Qepi[c+1][0]; e0_epi[z_dof] = Qepi[c+2][0]; + e1_epi[x_dof] = Qepi[c][1]; e1_epi[y_dof] = Qepi[c+1][1]; e1_epi[z_dof] = Qepi[c+2][1]; + e2_epi[x_dof] = Qepi[c][2]; e2_epi[y_dof] = Qepi[c+1][2]; e2_epi[z_dof] = Qepi[c+2][2]; + + #Qfiber[c:c+3][0:3] = bislerp(Qendo[c:c+3][0:3], Qepi[c:c+3][0:3], epi[scl]) + Qfiber[c:c+3][0:3] = my_bislerp(Qendo[c:c+3][0:3], Qepi[c:c+3][0:3], epi[scl]) + e0_fiber[x_dof] = Qfiber[c][0]; e0_fiber[y_dof] = Qfiber[c+1][0]; e0_fiber[z_dof] = Qfiber[c+2][0]; + e1_fiber[x_dof] = Qfiber[c][1]; e1_fiber[y_dof] = Qfiber[c+1][1]; e1_fiber[z_dof] = Qfiber[c+2][1]; + e2_fiber[x_dof] = Qfiber[c][2]; e2_fiber[y_dof] = Qfiber[c+1][2]; e2_fiber[z_dof] = Qfiber[c+2][2]; + + + cnt = cnt + 1; + c = c + 3; + + ''' + if(isrotatept): + points = [(-Sdof_coordinates[scl][2]+maxz)/10.0, Sdof_coordinates[scl][1]/10.0, Sdof_coordinates[scl][0]/10.0] + fvectors = [-1.0*e0_fiber[z_dof], e0_fiber[y_dof], e0_fiber[x_dof]] + svectors = [-1.0*e2_fiber[z_dof], e2_fiber[y_dof], e2_fiber[x_dof]] + + else: + points = [Sdof_coordinates[scl][0], Sdof_coordinates[scl][1], Sdof_coordinates[scl][2]] + fvectors = [e0_fiber[x_dof], e0_fiber[y_dof], e0_fiber[z_dof]] + svectors = [e2_fiber[x_dof], e2_fiber[y_dof], e2_fiber[z_dof]] + + print >>mtvfiberfile, points[0], points[1], points[2], fvectors[0], fvectors[1], fvectors[2] + print >>mtvsheetfile, points[0], points[1], points[2], svectors[0], svectors[1], svectors[2] + + ''' + + #print >> points[0], points[1], points[2], fvectors[0], fvectors[1], fvectors[2] + #print >> points[0], points[1], points[2], svectors[0], svectors[1], svectors[2] + + + + + + #func_of_vector.vector()[:] = e0_epi + #file1 = File("e0_epi.pvd") + #file1 << func_of_vector + # + #func_of_vector.vector()[:] = e1_epi + #file2 = File("e1_epi.pvd") + #file2 << func_of_vector + # + #func_of_vector.vector()[:] = e2_epi + #file3 = File("e2_epi.pvd") + #file3 << func_of_vector + # + #func_of_vector.vector()[:] = e0_rv + #file4 = File("e0_rv.pvd") + #file4 << func_of_vector + # + #func_of_vector.vector()[:] = e1_rv + #file5 = File("e1_rv.pvd") + #file5 << func_of_vector + # + #func_of_vector.vector()[:] = e2_rv + #file6 = File("e2_rv.pvd") + #file6 << func_of_vector + # + #func_of_vector.vector()[:] = e0_lv + #file7 = File("e0_lv.pvd") + #file7 << func_of_vector + # + #func_of_vector.vector()[:] = e1_lv + #file8 = File("e1_lv.pvd") + #file8 << func_of_vector + # + #func_of_vector.vector()[:] = e2_lv + #file9 = File("e2_lv.pvd") + #file9 << func_of_vector + # + #func_of_vector.vector()[:] = e0_endo + #file10 = File("e0_endo.pvd") + #file10 << func_of_vector + # + #func_of_vector.vector()[:] = e1_endo + #file11 = File("e1_endo.pvd") + #file11 << func_of_vector + # + #func_of_vector.vector()[:] = e2_endo + #file12 = File("e2_endo.pvd") + #file12 << func_of_vector + + pvdoutfile = outdirectory+outfilename+"_e0_fiber.pvd" + func_of_e1.vector()[:] = e0_fiber + func_of_e1.rename("fiber", "fiber") + file13 = File(pvdoutfile) + file13 << func_of_e1 + + pvdoutfile = outdirectory+outfilename+"_e1_fiber.pvd" + func_of_e2.vector()[:] = e1_fiber + func_of_e2.rename("sheet", "sheet") + file14 = File(pvdoutfile) + file14 << func_of_e2 + + pvdoutfile = outdirectory+outfilename+"_e2_fiber.pvd" + func_of_e3.rename("sheetnormal", "sheetnormal") + func_of_e3.vector()[:] = e2_fiber + file15 = File(pvdoutfile) + file15 << func_of_e3 + + print isrotatept + print outdirectory + outfilename + print "*******************************************************" + + if(isreturn): + + return func_of_e1, func_of_e2, func_of_e3 + +if (__name__ == "__main__"): + + parser = argparse.ArgumentParser() + parser.add_argument('--xml_folder', type=str, required=True) + parser.add_argument('--xml_meshfilename', type=str, required=True) + parser.add_argument('--xml_facetfilename', type=str, required=True) + parser.add_argument('--mtv_grid_directory', type=str, required=True) + parser.add_argument('--mtv_basename', type=str, required=True) + parser.add_argument('--isrotatept', type=bool, required=True) + parser.add_argument('--al_endo', type=float, required=True) + parser.add_argument('--al_epi', type=float, required=True) + parser.add_argument('--b_endo', type=float, required=True) + parser.add_argument('--b_epi', type=float, required=True) + args = parser.parse_args() + + print "************* Entering SetBiVFiber.py *****************" + + xmlmeshfilename = os.path.join(args.xml_folder, args.xml_meshfilename) + xmlfacetfilename = os.path.join(args.xml_folder, args.xml_facetfilename) + outdirectory = args.mtv_grid_directory + outfilename = args.mtv_basename + isrotatept = args.isrotatept + al_endo = args.al_endo + al_epi = args.al_epi + b_endo = args.b_endo + b_epi = args.b_epi + + mesh = Mesh(xmlmeshfilename) + boundaries = MeshFunction("size_t", mesh, xmlfacetfilename) + mtvfiberfilename = outdirectory+outfilename+"_fiber_rotated.axis" + mtvsheetfilename = outdirectory+outfilename+"_sheet_rotated.axis" + + SetBiVFiber(mesh, boundaries, mtvfiberfilename, mtvsheetfilename, al_endo, al_epi, b_endo, b_epi, isrotatept, outfilename, outdirectory) + diff --git a/vtk_py/SetBiVFiber_J.pyc b/vtk_py/SetBiVFiber_J.pyc new file mode 100644 index 0000000..0a4e677 Binary files /dev/null and b/vtk_py/SetBiVFiber_J.pyc differ diff --git a/vtk_py/SetBiVFiber_Quad.py b/vtk_py/SetBiVFiber_Quad.py new file mode 100644 index 0000000..d26edd5 --- /dev/null +++ b/vtk_py/SetBiVFiber_Quad.py @@ -0,0 +1,561 @@ +######################################################################## +import argparse +from mpi4py import MPI as pyMPI +import numpy as np +#from thLib import quat +import sys +import os +from dolfin import * +from sympy import Symbol, nsolve +import math +from scipy import linalg +from scipy import optimize +from cgkit.cgtypes import * +import vtk_py as vtk_py +######################################################################## + + +#def SetBiVFiber_Quad(mesh, boundaries, mtvfiberfilename, mtvsheetfilename, al_endo, al_epi, b_endo, b_epi, isrotatept, isreturn, outfilename, param, outdirectory="./", epiid=2, rvid=1, lvid=3, degree=2): +def SetBiVFiber_Quad(param): + + assert "mesh" in param, "No mesh is found" + assert "facetboundaries" in param, "No facetboundaries are found" + + mesh = param["mesh"] + boundaries = param["facetboundaries"] + matid = param["matid"] if ("matid" in param) else None + + epiid = param["epiid"] if ("epiid" in param) else 2 + lvid = param["lvid"] if ("lvid" in param) else 3 + rvid = param["rvid"] if ("rvid" in param) else 1 + outdirectory = param["outdirectory"] if ("outdirectory" in param) else "./" + isrotatept = param["isrotatept"] if ("isrotatept" in param) else False + isreturn = param["isreturn"] if ("isreturn" in param) else True + isLV = param["isLV"] if ("isLV" in param) else False + isscaling = param["isscaling"] if ("isscaling" in param) else False + outfilename = param["outfilename"] if ("outfilename" in param) else "fiber" + degree = param["degree"] if ("degree" in param) else 2 + mtvfiberfilename = param["mtvfiberfilename"] if ("mtvfiberfilename" in param) else None + mtvsheetfilename = param["mtvsheetfilename"] if ("mtvsheetfilename" in param) else None + + lvmatid = param["LV_matid"] if ("LV_matid" in param) else 0 + rvmatid = param["RV_matid"] if ("RV_matid" in param) else 0 + septummatid = param["Septum_matid"] if ("Septum_matid" in param) else 0 + + lv_fiber_angle = np.array(param["LV_fiber_angle"])*math.pi/180 if ("LV_fiber_angle" in param) else np.array([60, -60])*math.pi/180 + rv_fiber_angle = np.array(param["RV_fiber_angle"])*math.pi/180 if ("RV_fiber_angle" in param) else np.array([60, -60])*math.pi/180 + septum_fiber_angle = np.array(param["Septum_fiber_angle"])*math.pi/180 if ("Septum_fiber_angle" in param) else np.array([60, -60])*math.pi/180 + + lv_sheet_angle = np.array(param["LV_sheet_angle"])*math.pi/180 if ("LV_sheet_angle" in param) else np.array([0.1, -0.1])*math.pi/180 + rv_sheet_angle = np.array(param["RV_sheet_angle"])*math.pi/180 if ("RV_sheet_angle" in param) else np.array([0.1, -0.1])*math.pi/180 + septum_sheet_angle = np.array(param["Septum_sheet_angle"])*math.pi/180 if ("Septum_sheet_angle" in param) else np.array([0.1, -0.1])*math.pi/180 + + + # Set Fiber angle + #al_endo = al_endo*math.pi/180; b_endo = b_endo*math.pi/180; + #al_epi = al_epi*math.pi/180; b_epi = b_epi*math.pi/180; + + comm = mesh.mpi_comm().tompi4py() + + minz = comm.allreduce(np.amin(mesh.coordinates()[:,2]), op=pyMPI.MIN) + maxz = comm.allreduce(np.amax(mesh.coordinates()[:,2]), op=pyMPI.MAX) + + + # Boundary condition for Laplace equation from the bottom to the top + + def right_boundary(x): + return x[2] < minz+1.0 + + # Function that solves the Laplace equation and and calculates the gradient of the solution + def lap(Me, boud, par,op, filename): + + set_log_level(40) + parameters["form_compiler"]["quadrature_degree"] = degree + parameters["form_compiler"]["representation"] = 'quadrature' + + epi=epiid; rv=rvid; lv=lvid; + # Create mesh and define function space + mesh = Me + V = FunctionSpace(mesh, FiniteElement("Lagrange", mesh.ufl_cell(), 2)) + SQuad = FunctionSpace(mesh, FiniteElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + + y = mesh.coordinates() + sa = y.shape + ttt = y[:, 2].min() + cord = np.argwhere(y == ttt); + point = y[cord[0,0],:] + #print sa, cord, point + u0 = Constant(0.0) + if op == 1: + bc =[ DirichletBC(V, u0, right_boundary), DirichletBC(V, 1, boud, 4)] + # Define boundary conditions + else: + bc = [DirichletBC(V, par[0], boud, lv), DirichletBC(V, par[1], boud, epi ), DirichletBC(V, par[2], boud, rv)] + + # Define variational problem + u = TrialFunction(V) + v = TestFunction(V) + f = Constant(0) + a = inner(nabla_grad(u), nabla_grad(v))*dx + L = f*v*dx + + # Compute solution + u = Function(V) + solve(a == L, u, bc)#, solver_parameters={"linear_solver": "petsc"}) + u_a = u.vector().array() + u_a_quad = project(u, SQuad).vector().get_local()#, solver_type="petsc").vector().array() + + + # Compute gradient + V_g = FunctionSpace(mesh, VectorElement("Lagrange", mesh.ufl_cell(), 2)) + VQuad = FunctionSpace(mesh, VectorElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + v = TestFunction(V_g) + w = TrialFunction(V_g) + + a = inner(w, v)*dx + L = inner(grad(u), v)*dx + grad_u = Function(V_g) + solve(a == L, grad_u)#, solver_parameters={"linear_solver": "petsc"}) + grad_u_quad = project(grad_u, VQuad)#, solver_type="petsc") + grad_u.rename('grad_u', 'continuous gradient field') + grad_ua_quad = grad_u_quad.vector().get_local()#.array() + + + #plot(u, interactive=True) + + # Dump solution to file in VTK format + #newfilename = filename + '.pvd' + #file1= File(newfilename) + #file1<< u + + #newfilename = filename + 'grad.pvd' + #file2 = File(newfilename) + #file2 << grad_u + + # Hold plot + #interactive() + return u_a_quad, grad_ua_quad + + # Function to calculate the lenght of the vector + + def len_vec(vec): + l = (vec[0]**2 + vec[1]**2 + vec[2]**2)**0.5 + return l + + + + ################################################################################################## + # Function to calculate the orthogonal axis using the gradients calculated in the previous step + ################################################################################################### + def L1(e0, v0): + + L1x = (v0[0] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[0])**2 + L1y = (v0[1] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[1])**2 + L1z = (v0[2] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[2])**2 + + return (L1x + L1y + L1z)**0.5; + + def P(e0, v0): + + P1x = v0[0] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[0] + P1y = v0[1] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[1] + P1z = v0[2] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[2] + + return [P1x, P1y, P1z]; + + def function_e0(e0, v0, e1): + + f = [L1(e0,v0)*e0[0] - (e1[1]*P(e0,v0)[2] - e1[2]*P(e0,v0)[1]), + L1(e0,v0)*e0[1] - (e1[2]*P(e0,v0)[0] - e1[0]*P(e0,v0)[2]), + L1(e0,v0)*e0[2] - (e1[0]*P(e0,v0)[1] - e1[1]*P(e0,v0)[0])] + + return f; + + + def axisf(vec1, vec2): + + len_vec2 = len_vec(vec2); len_vec1 = len_vec(vec1); + e1 = vec1/len_vec1; ini_e2 = vec2/len_vec2; + ini_e0 = np.cross(e1, ini_e2) + + + e0 = np.zeros(3); e2 = np.zeros(3); + + # Solve using numerical + def function_wrap(e0): + return function_e0(e0, vec2, e1) + + sol = optimize.root(function_wrap, [ini_e0[0], ini_e0[1], ini_e0[2]], method='hybr') + e0[0] = sol.x[0]; e0[1] = sol.x[1]; e0[2] = sol.x[2]; + e2 = P(e0, vec2); + len_e2 = len_vec(e2) + e2[0] = e2[0]/len_e2; e2[1] = e2[1]/len_e2; e2[2] = e2[2]/len_e2; + + Q = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + + + return Q + + + ################################################################################################# + #Function to ensure the that the axis are orthogonal + ################################################################################################# + def orto(Q, cnt): + e0 = np.zeros(3); e1 = np.zeros(3); e2 = np.zeros(3); + e0[0] = Q[0][0]; e0[1] = Q[1][0]; e0[2] = Q[2][0]; + e1[0] = Q[0][1]; e1[1] = Q[1][1]; e1[2] = Q[2][1]; + e2[0] = Q[0][2]; e2[1] = Q[1][2]; e2[2] = Q[2][2]; + e0x = Symbol('e0x'); e0y = Symbol('e0y') ; e0z = Symbol('e0z'); e2x = Symbol('e2x'); e2y = Symbol('e2y') ; e2z = Symbol('e2z'); + + + try: + + aa = nsolve( [ e0x - e1[1]*e2z + e1[2]*e2y, e0y - e1[2]*e2x + e1[0]*e2z, e0z - e1[0]*e2y + e1[1]*e2x, e1[0] - e2y*e0z + e2z*e0y, e1[1] - e2z*e0x + e2x*e0z, e1[2] - e2x*e0y + e2y*e0x ], [ e0x, e0y, e0z, e2x, e2y, e2z ],[e0[0], e0[1], e0[2], e2[0], e2[1],e2[2] ]) + + + + e0[0] = aa[0]; e0[1] = aa[1]; e0[2] = aa[2]; + e2[0] = aa[3]; e2[1] = aa[4]; e2[2] = aa[5]; + Qa = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + + except ZeroDivisionError as detail: + print 'Handling run-time error:', detail + Qa = Q + f = quat.rotmat2quat(Qa) + outfile = open("quat.txt", "w") + print >>outfile, cnt, " ", f + return Qa + + + def orto3(Q, cnt): + + Q2 = np.dot(np.transpose(Q),Q) + Q2inv = np.linalg.inv(Q2) + sqrtQ2 = linalg.sqrtm(Q2inv) + Qa = np.dot(Q,sqrtQ2) + + return Qa + + ################################################################################################# + #Function to ensure the that the axis are orthogonal but this one is not working prorperly + ################################################################################################# + + def orto2(Q): + e0 = np.zeros(3); e1 = np.zeros(3); e2 = np.zeros(3); + e0[0] = Q[0][0]; e0[1] = Q[1][0]; e0[2] = Q[2][0]; + e1[0] = Q[0][1]; e1[1] = Q[1][1]; e1[2] = Q[2][1]; + e2[0] = Q[0][2]; e2[1] = Q[1][2]; e2[2] = Q[2][2]; + + while np.dot(e0, e1) + np.dot(e0, e2) + np.dot(e1, e2) > 10e-30: + e2 = np.cross(e0, e1); + e0 = np.cross(e1, e2); + Qa = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + return Qa + + ############################################################################################## + #Function 3 - This function rotates the axis calculated in the previous steps + ############################################################################################## + + def orient(Q, al, bt): + arr1 =np.array( [[np.cos(al), -np.sin(al), 0 ],[np.sin(al), np.cos(al), 0],[0, 0, 1]]); + arr2 = np.array([[1, 0, 0],[0, np.cos(bt), np.sin(bt) ],[0, -np.sin(bt), np.cos(bt) ]]); + out = np.dot(Q, arr1, arr2) + return out + + ################################################################################################## + #Function 4 - This function calculates quarternions and interpolates these quarternions + ################################################################################################# + + + def bislerp(Qa, Qb, t): + + Qa_M = mat3([Qa[0,0], Qa[0,1], Qa[0,2], Qa[1,0], Qa[1,1], Qa[1,2], Qa[2,0], Qa[2,1], Qa[2,2]]) + Qb_M = mat3([Qb[0,0], Qb[0,1], Qb[0,2], Qb[1,0], Qb[1,1], Qb[1,2], Qb[2,0], Qb[2,1], Qb[2,2]]) + qa = quat(Qa_M) + qb = quat(Qb_M) + + val = np.zeros(8) + quat_i = quat(0,1,0,0) + quat_j = quat(0,0,1,0) + quat_k = quat(0,0,0,1) + quat_array = [qa, -qa, qa*quat_i, -qa*quat_i, qa*quat_j, -qa*quat_j, qa*quat_k, -qa*quat_k] + cnt = 0 + for qt in quat_array: + val[cnt] = qt.dot(qb) + cnt = cnt + 1 + + qt = quat_array[val.argmax(axis=0)] + + if(t < 0): + t = 0.0 + + + qm = slerp(t, qt, qb) + qm = qm.normalize() + Qm_M = qm.toMat3() + Qm = [[Qm_M[0,0], Qm_M[0,1], Qm_M[0,2]], [Qm_M[1,0], Qm_M[1,1], Qm_M[1,2]], [Qm_M[2,0], Qm_M[2,1], Qm_M[2,2]]] + + return Qm + + + + ################################################################################################# + ######Generating results and using the functions ########## + ################################################################################################# + # DOF map + parameters["form_compiler"]["quadrature_degree"] = degree + parameters["form_compiler"]["representation"] = 'quadrature' + + V = FunctionSpace(mesh, VectorElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + S = FunctionSpace(mesh, FiniteElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + + dof_coordinates = V.tabulate_dof_coordinates() + Sdof_coordinates = S.tabulate_dof_coordinates() + n = V.dim() + d = mesh.geometry().dim() + dof_coordinates.resize((n, d)) + Sdof_coordinates.resize((n,d)) + + x_my_first, x_my_last = V.sub(0).dofmap().ownership_range() + x_dofs = np.arange(0, x_my_last-x_my_first, d) + y_dofs = np.arange(1, x_my_last-x_my_first, d) + z_dofs = np.arange(2, x_my_last-x_my_first, d) + + + jj = np.array([ 1, 1, 1] ); hh = np.array([1, 1, 1]); + + + ####### Solving the poisson equation ############ + + # case 1) epi -> u = 0 and rv/lv -> u = 1 + + if(MPI.rank(mpi_comm_world()) == 0): + print "Solve Poisson Eq. 1, epi -> u = 0 and rv/lv -> u = 1" + par1 = [0, 1, 0]; epi, dd = lap(mesh, boundaries, par1, 0, 'phi_epi') + + #total_dd = comm.allreduce(len(dd), op=pyMPI.SUM) + #num_of_nodes = total_dd/3 + #scalar_array = np.zeros(num_of_nodes) + #scalar_dof = S.dofmap().dofs() + + total_dd = len(dd) + S_my_first, S_my_last = S.dofmap().ownership_range() + scalar_dof = filter(lambda dof: S.dofmap().local_to_global_index(dof) not in S.dofmap().local_to_global_unowned(), + xrange(S_my_last-S_my_first)) + + + # case 2) lv -> u = 0 and rv/epi -> u = 1 + + if(MPI.rank(mpi_comm_world()) == 0): + print "Solve Poisson Eq. 2, lv -> u = 0 and rv/epi -> u = 1" + par2 = [1, 0, 0]; lv, dd2 = lap(mesh, boundaries, par2, 0, 'phi_lv'); #dd2 = -1*dd2 + + # case 3) rv -> u = 0 and epi/lv -> u = 1 + + if(MPI.rank(mpi_comm_world()) == 0): + print "Solve Poisson Eq. 3, rv -> u = 0 and epi/lv -> u = 1" + par3 = [0, 0, 1]; rv, dd3 = lap(mesh, boundaries, par3, 0, 'phi_rv') + + #case 4) from the top to the bottom + + if(MPI.rank(mpi_comm_world()) == 0): + print "Solve Poisson Eq. 4, from the top to the bottom" + par1 = [0, 1, 0]; b, dd4 = lap(mesh, boundaries, par1, 1, 'phi_ab') + + + + # Start calculating the fiber orientation + cnt = 0; c = 0; + vector_array = np.zeros(V.dim()) + + func_of_vector = Function(V); + func_of_scalar = Function(S); + + func_of_e0 = Function(V); + func_of_e1 = Function(V); + func_of_e2 = Function(V); + + func_of_e0_vector = func_of_e0.vector() + func_of_e1_vector = func_of_e1.vector() + func_of_e2_vector = func_of_e2.vector() + + e0_fiber = func_of_e0_vector.get_local() + e1_fiber = func_of_e1_vector.get_local() + e2_fiber = func_of_e2_vector.get_local() + + vec_dd = np.zeros(3); vec_dd2 = np.zeros(3); vec_dd3 = np.zeros(3); vec_dd4 = np.zeros(3); + + Qepi = np.zeros((total_dd,3)); Qrv = np.zeros((total_dd,3)); Qlv = np.zeros((total_dd,3)); + Qendo = np.zeros((total_dd,3)) + Qfiber = np.zeros((total_dd,3)) + + e0_epi = np.zeros(total_dd); e1_epi = np.zeros(total_dd); e2_epi = np.zeros(total_dd); + e0_rv = np.zeros(total_dd); e1_rv = np.zeros(total_dd); e2_rv = np.zeros(total_dd); + e0_lv = np.zeros(total_dd); e1_lv = np.zeros(total_dd); e2_lv = np.zeros(total_dd); + check = np.zeros(total_dd); check2 = np.zeros(total_dd); + ds = np.zeros(total_dd/3); al_s = np.zeros(total_dd/3); b_s = np.zeros(total_dd/3); + al_w = np.zeros(total_dd/3); b_w = np.zeros(total_dd/3); + + e0_endo = np.zeros(total_dd); e1_endo = np.zeros(total_dd); e2_endo = np.zeros(total_dd); + + + # Open MTV fiber and sheet files + if( MPI.rank(mpi_comm_world()) == 0): + + if(mtvfiberfilename): + mtvfiberfile = open(mtvfiberfilename, 'w') + print >>mtvfiberfile, total_dd/3, 10 + + + if(mtvsheetfilename): + mtvsheetfile = open(mtvsheetfilename, 'w') + print >>mtvsheetfile, total_dd/3 + + + for x_dof, y_dof, z_dof, scl in zip(x_dofs, y_dofs, z_dofs, scalar_dof): + + + if(abs(rv[scl]) < 1e-9 and abs(rv[scl] + lv[scl]) < 1e-9): + ds[scl] = 0.0 + else: + ds[scl] = rv[scl]/(lv[scl]+rv[scl]) + + + pt = Point(np.array([Sdof_coordinates[scl][0], Sdof_coordinates[scl][1], Sdof_coordinates[scl][2]])) + meshid = mesh.bounding_box_tree().compute_first_collision(pt) + + al_endo = lv_fiber_angle[0]; b_endo = lv_sheet_angle[0]; + al_epi = lv_fiber_angle[1]; b_epi = lv_sheet_angle[1]; + + if matid is not None: + if(matid.array()[meshid] == septummatid): + al_endo = septum_fiber_angle[0]; b_endo = septum_sheet_angle[0]; + al_epi = septum_fiber_angle[1]; b_epi = septum_sheet_angle[1]; + elif(matid.array()[meshid] == rvmatid): + al_endo = rv_fiber_angle[0]; b_endo = rv_sheet_angle[0]; + al_epi = rv_fiber_angle[1]; b_epi = rv_sheet_angle[1]; + + + al_s[scl] = al_endo*(1 - ds[scl]) - al_endo*ds[scl]; b_s[scl] = b_endo*(1 - ds[scl]) - b_endo*ds[scl]; + al_w[scl] = al_endo*(1 - epi[scl]) + al_epi*epi[scl]; b_w[scl] = b_endo*(1 - epi[scl]) + b_epi*epi[scl]; + + vec_dd[0] = dd[x_dof]; vec_dd[1] = dd[y_dof]; vec_dd[2] = dd[z_dof]; + vec_dd2[0] = dd2[x_dof]; vec_dd2[1] = dd2[y_dof]; vec_dd2[2] = dd2[z_dof]; + vec_dd3[0] = dd3[x_dof]; vec_dd3[1] = dd3[y_dof]; vec_dd3[2] = dd3[z_dof]; + vec_dd4[0] = dd4[x_dof]; vec_dd4[1] = dd4[y_dof]; vec_dd4[2] = dd4[z_dof]; + + + Qlv[c:c+3][0:3]= axisf(vec_dd4, -1.0*vec_dd2); + Qlv[c:c+3][0:3] = orto3(Qlv[c:c+3][0:3], cnt); + Qlv[c:c+3][0:3]= orient(Qlv[c:c+3][0:3], al_s[scl], b_s[scl]) + + + e0_lv[x_dof] = Qlv[c][0]; e0_lv[y_dof] = Qlv[c+1][0]; e0_lv[z_dof] = Qlv[c+2][0]; + e1_lv[x_dof] = Qlv[c][1]; e1_lv[y_dof] = Qlv[c+1][1]; e1_lv[z_dof] = Qlv[c+2][1]; + e2_lv[x_dof] = Qlv[c][2]; e2_lv[y_dof] = Qlv[c+1][2]; e2_lv[z_dof] = Qlv[c+2][2]; + + Qrv[c:c+3][0:3] = axisf(vec_dd4, -1.0*vec_dd3); + Qrv[c:c+3][0:3] = orto3(Qrv[c:c+3][0:3], cnt); + Qrv[c:c+3][0:3]= orient(Qrv[c:c+3][0:3], -al_s[scl], -b_s[scl]); + + e0_rv[x_dof] = Qrv[c][0]; e0_rv[y_dof] = Qrv[c+1][0]; e0_rv[z_dof] = Qrv[c+2][0]; + e1_rv[x_dof] = Qrv[c][1]; e1_rv[y_dof] = Qrv[c+1][1]; e1_rv[z_dof] = Qrv[c+2][1]; + e2_rv[x_dof] = Qrv[c][2]; e2_rv[y_dof] = Qrv[c+1][2]; e2_rv[z_dof] = Qrv[c+2][2]; + + + Qendo[c:c+3][0:3] = bislerp(Qlv[c:c+3][0:3], Qrv[c:c+3][0:3], ds[scl]) + e0_endo[x_dof] = Qendo[c][0]; e0_endo[y_dof] = Qendo[c+1][0]; e0_endo[z_dof] = Qendo[c+2][0]; + e1_endo[x_dof] = Qendo[c][1]; e1_endo[y_dof] = Qendo[c+1][1]; e1_endo[z_dof] = Qendo[c+2][1]; + e2_endo[x_dof] = Qendo[c][2]; e2_endo[y_dof] = Qendo[c+1][2]; e2_endo[z_dof] = Qendo[c+2][2]; + + + Qepi[c:c+3][0:3] = axisf(vec_dd4, vec_dd); + Qepi[c:c+3][0:3] = orto3(Qepi[c:c+3][0:3], cnt); + Qepi[c:c+3][0:3] = orient(Qepi[c:c+3][0:3], al_w[scl], b_w[scl]); + + e0_epi[x_dof] = Qepi[c][0]; e0_epi[y_dof] = Qepi[c+1][0]; e0_epi[z_dof] = Qepi[c+2][0]; + e1_epi[x_dof] = Qepi[c][1]; e1_epi[y_dof] = Qepi[c+1][1]; e1_epi[z_dof] = Qepi[c+2][1]; + e2_epi[x_dof] = Qepi[c][2]; e2_epi[y_dof] = Qepi[c+1][2]; e2_epi[z_dof] = Qepi[c+2][2]; + + Qfiber[c:c+3][0:3] = bislerp(Qendo[c:c+3][0:3], Qepi[c:c+3][0:3], epi[scl]) + e0_fiber[x_dof] = Qfiber[c][0]; e0_fiber[y_dof] = Qfiber[c+1][0]; e0_fiber[z_dof] = Qfiber[c+2][0]; + e1_fiber[x_dof] = Qfiber[c][1]; e1_fiber[y_dof] = Qfiber[c+1][1]; e1_fiber[z_dof] = Qfiber[c+2][1]; + e2_fiber[x_dof] = Qfiber[c][2]; e2_fiber[y_dof] = Qfiber[c+1][2]; e2_fiber[z_dof] = Qfiber[c+2][2]; + + + cnt = cnt + 1; + c = c + 3; + + if(isrotatept): + points = [(-Sdof_coordinates[scl][2]+maxz)/10.0, Sdof_coordinates[scl][1]/10.0, Sdof_coordinates[scl][0]/10.0] + fvectors = [-1.0*e0_fiber[z_dof], e0_fiber[y_dof], e0_fiber[x_dof]] + svectors = [-1.0*e2_fiber[z_dof], e2_fiber[y_dof], e2_fiber[x_dof]] + + else: + points = [Sdof_coordinates[scl][0], Sdof_coordinates[scl][1], Sdof_coordinates[scl][2]] + fvectors = [e0_fiber[x_dof], e0_fiber[y_dof], e0_fiber[z_dof]] + svectors = [e2_fiber[x_dof], e2_fiber[y_dof], e2_fiber[z_dof]] + + + #print >>mtvfiberfile, points[0], points[1], points[2], fvectors[0], fvectors[1], fvectors[2] + #print >>mtvsheetfile, points[0], points[1], points[2], svectors[0], svectors[1], svectors[2] + + + vtkoutfile = outdirectory+outfilename+"_e0_fiber" + func_of_e0_vector.set_local(e0_fiber) + func_of_e0_vector.apply("insert") + vtk_py.convertQuadDataToVTK(mesh, V, func_of_e0, vtkoutfile) + + vtkoutfile = outdirectory+outfilename+"_e1_fiber" + func_of_e1_vector.set_local(e1_fiber) + func_of_e1_vector.apply("insert") + vtk_py.convertQuadDataToVTK(mesh, V, func_of_e1, vtkoutfile) + + vtkoutfile = outdirectory+outfilename+"_e2_fiber" + func_of_e2_vector.set_local(e2_fiber) + func_of_e2_vector.apply("insert") + vtk_py.convertQuadDataToVTK(mesh, V, func_of_e2, vtkoutfile) + + if(MPI.rank(mpi_comm_world()) == 0): + print isrotatept + print outdirectory + outfilename + print "*******************************************************" + + if(isreturn): + + return func_of_e0, func_of_e1, func_of_e2 + +if (__name__ == "__main__"): + + parser = argparse.ArgumentParser() + parser.add_argument('--xml_folder', type=str, required=True) + parser.add_argument('--xml_meshfilename', type=str, required=True) + parser.add_argument('--xml_facetfilename', type=str, required=True) + parser.add_argument('--mtv_grid_directory', type=str, required=True) + parser.add_argument('--mtv_basename', type=str, required=True) + parser.add_argument('--isrotatept', type=bool, required=True) + parser.add_argument('--al_endo', type=float, required=True) + parser.add_argument('--al_epi', type=float, required=True) + parser.add_argument('--b_endo', type=float, required=True) + parser.add_argument('--b_epi', type=float, required=True) + args = parser.parse_args() + + print "************* Entering SetBiVFiber.py *****************" + + xmlmeshfilename = os.path.join(args.xml_folder, args.xml_meshfilename) + xmlfacetfilename = os.path.join(args.xml_folder, args.xml_facetfilename) + outdirectory = args.mtv_grid_directory + outfilename = args.mtv_basename + isrotatept = args.isrotatept + al_endo = args.al_endo + al_epi = args.al_epi + b_endo = args.b_endo + b_epi = args.b_epi + + mesh = Mesh(xmlmeshfilename) + boundaries = MeshFunction("size_t", mesh, xmlfacetfilename) + mtvfiberfilename = outdirectory+outfilename+"_fiber_rotated.axis" + mtvsheetfilename = outdirectory+outfilename+"_sheet_rotated.axis" + + SetBiVFiber(mesh, boundaries, mtvfiberfilename, mtvsheetfilename, al_endo, al_epi, b_endo, b_epi, isrotatept, outfilename, outdirectory) + diff --git a/vtk_py/SetBiVFiber_Quad_PyQ.py b/vtk_py/SetBiVFiber_Quad_PyQ.py new file mode 100644 index 0000000..6b8c1cd --- /dev/null +++ b/vtk_py/SetBiVFiber_Quad_PyQ.py @@ -0,0 +1,622 @@ +######################################################################## +import argparse +from mpi4py import MPI as pyMPI +import numpy as np +#from thLib import quat +import sys +import os +from dolfin import * +from sympy import Symbol, nsolve +import math +from scipy import linalg +from scipy import optimize + +import vtk_py as vtk_py + +import pyquaternion as pyq +import pdb + + +######################################################################## + + +#def SetBiVFiber_Quad(mesh, boundaries, mtvfiberfilename, mtvsheetfilename, al_endo, al_epi, b_endo, b_epi, isrotatept, isreturn, outfilename, param, outdirectory="./", epiid=2, rvid=1, lvid=3, degree=2): +def SetBiVFiber_Quad_PyQ(param): + ''' + What: This function uses pyquaternion lib instead of cgkit for quarternion calculations + What more: pip install (http://kieranwynn.github.io/pyquaternion/) + + Where: my_bislerp() instead of bislerp() in SetBiVFiber_Quad + + How: vtk_py.SetBiVFiber_J( ... ) + + Plaussible issues: matrix to quaternion is not unique, topology is trickier + http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/tim.htm + http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ + + What else: comment out all other problematic lines + for eg., Sdof_coordinates + + ''' + + pdb.set_trace() + + assert "mesh" in param, "No mesh is found" + assert "facetboundaries" in param, "No facetboundaries are found" + + mesh = param["mesh"] + boundaries = param["facetboundaries"] + matid = param["matid"] if ("matid" in param) else None + + epiid = param["epiid"] if ("epiid" in param) else 2 + lvid = param["lvid"] if ("lvid" in param) else 3 + rvid = param["rvid"] if ("rvid" in param) else 1 + outdirectory = param["outdirectory"] if ("outdirectory" in param) else "./" + isrotatept = param["isrotatept"] if ("isrotatept" in param) else False + isreturn = param["isreturn"] if ("isreturn" in param) else True + isLV = param["isLV"] if ("isLV" in param) else False + isscaling = param["isscaling"] if ("isscaling" in param) else False + outfilename = param["outfilename"] if ("outfilename" in param) else "fiber" + degree = param["degree"] if ("degree" in param) else 2 + mtvfiberfilename = param["mtvfiberfilename"] if ("mtvfiberfilename" in param) else None + mtvsheetfilename = param["mtvsheetfilename"] if ("mtvsheetfilename" in param) else None + + lvmatid = param["LV_matid"] if ("LV_matid" in param) else 0 + rvmatid = param["RV_matid"] if ("RV_matid" in param) else 0 + septummatid = param["Septum_matid"] if ("Septum_matid" in param) else 0 + + lv_fiber_angle = np.array(param["LV_fiber_angle"])*math.pi/180 if ("LV_fiber_angle" in param) else np.array([60, -60])*math.pi/180 + rv_fiber_angle = np.array(param["RV_fiber_angle"])*math.pi/180 if ("RV_fiber_angle" in param) else np.array([60, -60])*math.pi/180 + septum_fiber_angle = np.array(param["Septum_fiber_angle"])*math.pi/180 if ("Septum_fiber_angle" in param) else np.array([60, -60])*math.pi/180 + + lv_sheet_angle = np.array(param["LV_sheet_angle"])*math.pi/180 if ("LV_sheet_angle" in param) else np.array([0.1, -0.1])*math.pi/180 + rv_sheet_angle = np.array(param["RV_sheet_angle"])*math.pi/180 if ("RV_sheet_angle" in param) else np.array([0.1, -0.1])*math.pi/180 + septum_sheet_angle = np.array(param["Septum_sheet_angle"])*math.pi/180 if ("Septum_sheet_angle" in param) else np.array([0.1, -0.1])*math.pi/180 + + + # Set Fiber angle + #al_endo = al_endo*math.pi/180; b_endo = b_endo*math.pi/180; + #al_epi = al_epi*math.pi/180; b_epi = b_epi*math.pi/180; + + comm = mesh.mpi_comm().tompi4py() + + minz = comm.allreduce(np.amin(mesh.coordinates()[:,2]), op=pyMPI.MIN) + maxz = comm.allreduce(np.amax(mesh.coordinates()[:,2]), op=pyMPI.MAX) + + + # Boundary condition for Laplace equation from the bottom to the top + + def right_boundary(x): + return x[2] < minz+1.0 + + # Function that solves the Laplace equation and and calculates the gradient of the solution + def lap(Me, boud, par,op, filename): + + set_log_level(40) + parameters["form_compiler"]["quadrature_degree"] = degree + parameters["form_compiler"]["representation"] = 'quadrature' + + epi=epiid; rv=rvid; lv=lvid; + # Create mesh and define function space + mesh = Me + V = FunctionSpace(mesh, FiniteElement("Lagrange", mesh.ufl_cell(), 2)) + SQuad = FunctionSpace(mesh, FiniteElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + + y = mesh.coordinates() + sa = y.shape + ttt = y[:, 2].min() + cord = np.argwhere(y == ttt); + point = y[cord[0,0],:] + #print sa, cord, point + u0 = Constant(0.0) + if op == 1: + bc =[ DirichletBC(V, u0, right_boundary), DirichletBC(V, 1, boud, 4)] + # Define boundary conditions + else: + bc = [DirichletBC(V, par[0], boud, lv), DirichletBC(V, par[1], boud, epi ), DirichletBC(V, par[2], boud, rv)] + + # Define variational problem + u = TrialFunction(V) + v = TestFunction(V) + f = Constant(0) + a = inner(nabla_grad(u), nabla_grad(v))*dx + L = f*v*dx + + # Compute solution + u = Function(V) + solve(a == L, u, bc)#, solver_parameters={"linear_solver": "petsc"}) + u_a = u.vector().array() + u_a_quad = project(u, SQuad).vector().get_local()#, solver_type="petsc").vector().array() + + + # Compute gradient + V_g = FunctionSpace(mesh, VectorElement("Lagrange", mesh.ufl_cell(), 2)) + VQuad = FunctionSpace(mesh, VectorElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + v = TestFunction(V_g) + w = TrialFunction(V_g) + + a = inner(w, v)*dx + L = inner(grad(u), v)*dx + grad_u = Function(V_g) + solve(a == L, grad_u)#, solver_parameters={"linear_solver": "petsc"}) + grad_u_quad = project(grad_u, VQuad)#, solver_type="petsc") + grad_u.rename('grad_u', 'continuous gradient field') + grad_ua_quad = grad_u_quad.vector().get_local()#.array() + + + #plot(u, interactive=True) + + # Dump solution to file in VTK format + #newfilename = filename + '.pvd' + #file1= File(newfilename) + #file1<< u + + #newfilename = filename + 'grad.pvd' + #file2 = File(newfilename) + #file2 << grad_u + + # Hold plot + #interactive() + return u_a_quad, grad_ua_quad + + # Function to calculate the lenght of the vector + + def len_vec(vec): + l = (vec[0]**2 + vec[1]**2 + vec[2]**2)**0.5 + return l + + + + ################################################################################################## + # Function to calculate the orthogonal axis using the gradients calculated in the previous step + ################################################################################################### + def L1(e0, v0): + + L1x = (v0[0] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[0])**2 + L1y = (v0[1] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[1])**2 + L1z = (v0[2] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[2])**2 + + return (L1x + L1y + L1z)**0.5; + + def P(e0, v0): + + P1x = v0[0] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[0] + P1y = v0[1] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[1] + P1z = v0[2] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[2] + + return [P1x, P1y, P1z]; + + def function_e0(e0, v0, e1): + + f = [L1(e0,v0)*e0[0] - (e1[1]*P(e0,v0)[2] - e1[2]*P(e0,v0)[1]), + L1(e0,v0)*e0[1] - (e1[2]*P(e0,v0)[0] - e1[0]*P(e0,v0)[2]), + L1(e0,v0)*e0[2] - (e1[0]*P(e0,v0)[1] - e1[1]*P(e0,v0)[0])] + + return f; + + + def axisf(vec1, vec2): + + len_vec2 = len_vec(vec2); len_vec1 = len_vec(vec1); + e1 = vec1/len_vec1; ini_e2 = vec2/len_vec2; + ini_e0 = np.cross(e1, ini_e2) + + + e0 = np.zeros(3); e2 = np.zeros(3); + + # Solve using numerical + def function_wrap(e0): + return function_e0(e0, vec2, e1) + + sol = optimize.root(function_wrap, [ini_e0[0], ini_e0[1], ini_e0[2]], method='hybr') + e0[0] = sol.x[0]; e0[1] = sol.x[1]; e0[2] = sol.x[2]; + e2 = P(e0, vec2); + len_e2 = len_vec(e2) + e2[0] = e2[0]/len_e2; e2[1] = e2[1]/len_e2; e2[2] = e2[2]/len_e2; + + Q = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + + + return Q + + + ################################################################################################# + #Function to ensure the that the axis are orthogonal + ################################################################################################# + def orto(Q, cnt): + e0 = np.zeros(3); e1 = np.zeros(3); e2 = np.zeros(3); + e0[0] = Q[0][0]; e0[1] = Q[1][0]; e0[2] = Q[2][0]; + e1[0] = Q[0][1]; e1[1] = Q[1][1]; e1[2] = Q[2][1]; + e2[0] = Q[0][2]; e2[1] = Q[1][2]; e2[2] = Q[2][2]; + e0x = Symbol('e0x'); e0y = Symbol('e0y') ; e0z = Symbol('e0z'); e2x = Symbol('e2x'); e2y = Symbol('e2y') ; e2z = Symbol('e2z'); + + + try: + + aa = nsolve( [ e0x - e1[1]*e2z + e1[2]*e2y, e0y - e1[2]*e2x + e1[0]*e2z, e0z - e1[0]*e2y + e1[1]*e2x, e1[0] - e2y*e0z + e2z*e0y, e1[1] - e2z*e0x + e2x*e0z, e1[2] - e2x*e0y + e2y*e0x ], [ e0x, e0y, e0z, e2x, e2y, e2z ],[e0[0], e0[1], e0[2], e2[0], e2[1],e2[2] ]) + + + + e0[0] = aa[0]; e0[1] = aa[1]; e0[2] = aa[2]; + e2[0] = aa[3]; e2[1] = aa[4]; e2[2] = aa[5]; + Qa = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + + except ZeroDivisionError as detail: + print 'Handling run-time error:', detail + Qa = Q + f = quat.rotmat2quat(Qa) + outfile = open("quat.txt", "w") + print >>outfile, cnt, " ", f + return Qa + + + def orto3(Q, cnt): + + Q2 = np.dot(np.transpose(Q),Q) + Q2inv = np.linalg.inv(Q2) + sqrtQ2 = linalg.sqrtm(Q2inv) + Qa = np.dot(Q,sqrtQ2) + + return Qa + + ################################################################################################# + #Function to ensure the that the axis are orthogonal but this one is not working prorperly + ################################################################################################# + + def orto2(Q): + e0 = np.zeros(3); e1 = np.zeros(3); e2 = np.zeros(3); + e0[0] = Q[0][0]; e0[1] = Q[1][0]; e0[2] = Q[2][0]; + e1[0] = Q[0][1]; e1[1] = Q[1][1]; e1[2] = Q[2][1]; + e2[0] = Q[0][2]; e2[1] = Q[1][2]; e2[2] = Q[2][2]; + + while np.dot(e0, e1) + np.dot(e0, e2) + np.dot(e1, e2) > 10e-30: + e2 = np.cross(e0, e1); + e0 = np.cross(e1, e2); + Qa = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + return Qa + + ############################################################################################## + #Function 3 - This function rotates the axis calculated in the previous steps + ############################################################################################## + + def orient(Q, al, bt): + arr1 =np.array( [[np.cos(al), -np.sin(al), 0 ],[np.sin(al), np.cos(al), 0],[0, 0, 1]]); + arr2 = np.array([[1, 0, 0],[0, np.cos(bt), np.sin(bt) ],[0, -np.sin(bt), np.cos(bt) ]]); + out = np.dot(Q, arr1, arr2) + return out + + ################################################################################################## + #Function 4 - This function calculates quarternions and interpolates these quarternions + ################################################################################################# + + def bislerp(Qa, Qb, t): + + Qa_M = mat3([Qa[0,0], Qa[0,1], Qa[0,2], Qa[1,0], Qa[1,1], Qa[1,2], Qa[2,0], Qa[2,1], Qa[2,2]]) + Qb_M = mat3([Qb[0,0], Qb[0,1], Qb[0,2], Qb[1,0], Qb[1,1], Qb[1,2], Qb[2,0], Qb[2,1], Qb[2,2]]) + qa = quat(Qa_M) + qb = quat(Qb_M) + + val = np.zeros(8) + quat_i = quat(0,1,0,0) + quat_j = quat(0,0,1,0) + quat_k = quat(0,0,0,1) + quat_array = [qa, -qa, qa*quat_i, -qa*quat_i, qa*quat_j, -qa*quat_j, qa*quat_k, -qa*quat_k] + cnt = 0 + for qt in quat_array: + val[cnt] = qt.dot(qb) + cnt = cnt + 1 + + qt = quat_array[val.argmax(axis=0)] + + if(t < 0): + t = 0.0 + + + qm = slerp(t, qt, qb) + qm = qm.normalize() + Qm_M = qm.toMat3() + Qm = [[Qm_M[0,0], Qm_M[0,1], Qm_M[0,2]], [Qm_M[1,0], Qm_M[1,1], Qm_M[1,2]], [Qm_M[2,0], Qm_M[2,1], Qm_M[2,2]]] + + return Qm + + def my_bislerp(Qa, Qb, t): + + qa = pyq.Quaternion(matrix=Qa) + qb = pyq.Quaternion(matrix=Qb) + + + val = np.zeros(8) + + quat_i = pyq.Quaternion(0,1,0,0) + quat_j = pyq.Quaternion(0,0,1,0) + quat_k = pyq.Quaternion(0,0,0,1) + + quat_array = [qa, -qa, qa*quat_i, -qa*quat_i, qa*quat_j, -qa*quat_j, qa*quat_k, -qa*quat_k] + + cnt = 0 + qb_arr = np.array([qb[0], qb[1], qb[2], qb[3]]) + + for qt in quat_array: + #val[cnt] = qt.dot(qb) + qt_arr = np.array([qt[0], qt[1], qt[2], qt[3]]) + val[cnt] = np.dot(qt_arr, qb_arr) + cnt = cnt + 1 + + qt = quat_array[val.argmax(axis=0)] + + if(t < 0): + t = 0.0 + + #qm = slerp(t, qt, qb) + qm = pyq.Quaternion.slerp(qt, qb, t) + qm = qm.normalised + Qm_M = qm.rotation_matrix + + return Qm_M + + + + ################################################################################################# + ######Generating results and using the functions ########## + ################################################################################################# + # DOF map + parameters["form_compiler"]["quadrature_degree"] = degree + parameters["form_compiler"]["representation"] = 'quadrature' + + V = FunctionSpace(mesh, VectorElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + S = FunctionSpace(mesh, FiniteElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + + dof_coordinates = V.tabulate_dof_coordinates() + Sdof_coordinates = S.tabulate_dof_coordinates() + n = V.dim() + d = mesh.geometry().dim() + dof_coordinates.resize((n, d)) + Sdof_coordinates.resize((n,d)) + + x_my_first, x_my_last = V.sub(0).dofmap().ownership_range() + x_dofs = np.arange(0, x_my_last-x_my_first, d) + y_dofs = np.arange(1, x_my_last-x_my_first, d) + z_dofs = np.arange(2, x_my_last-x_my_first, d) + + + jj = np.array([ 1, 1, 1] ); hh = np.array([1, 1, 1]); + + + ####### Solving the poisson equation ############ + + # case 1) epi -> u = 0 and rv/lv -> u = 1 + + if(MPI.rank(mpi_comm_world()) == 0): + print "Solve Poisson Eq. 1, epi -> u = 0 and rv/lv -> u = 1" + par1 = [0, 1, 0]; epi, dd = lap(mesh, boundaries, par1, 0, 'phi_epi') + + #total_dd = comm.allreduce(len(dd), op=pyMPI.SUM) + #num_of_nodes = total_dd/3 + #scalar_array = np.zeros(num_of_nodes) + #scalar_dof = S.dofmap().dofs() + + total_dd = len(dd) + S_my_first, S_my_last = S.dofmap().ownership_range() + scalar_dof = filter(lambda dof: S.dofmap().local_to_global_index(dof) not in S.dofmap().local_to_global_unowned(), + xrange(S_my_last-S_my_first)) + + + # case 2) lv -> u = 0 and rv/epi -> u = 1 + + if(MPI.rank(mpi_comm_world()) == 0): + print "Solve Poisson Eq. 2, lv -> u = 0 and rv/epi -> u = 1" + par2 = [1, 0, 0]; lv, dd2 = lap(mesh, boundaries, par2, 0, 'phi_lv'); #dd2 = -1*dd2 + + # case 3) rv -> u = 0 and epi/lv -> u = 1 + + if(MPI.rank(mpi_comm_world()) == 0): + print "Solve Poisson Eq. 3, rv -> u = 0 and epi/lv -> u = 1" + par3 = [0, 0, 1]; rv, dd3 = lap(mesh, boundaries, par3, 0, 'phi_rv') + + #case 4) from the top to the bottom + + if(MPI.rank(mpi_comm_world()) == 0): + print "Solve Poisson Eq. 4, from the top to the bottom" + par1 = [0, 1, 0]; b, dd4 = lap(mesh, boundaries, par1, 1, 'phi_ab') + + + + # Start calculating the fiber orientation + cnt = 0; c = 0; + vector_array = np.zeros(V.dim()) + + func_of_vector = Function(V); + func_of_scalar = Function(S); + + func_of_e0 = Function(V); + func_of_e1 = Function(V); + func_of_e2 = Function(V); + + func_of_e0_vector = func_of_e0.vector() + func_of_e1_vector = func_of_e1.vector() + func_of_e2_vector = func_of_e2.vector() + + e0_fiber = func_of_e0_vector.get_local() + e1_fiber = func_of_e1_vector.get_local() + e2_fiber = func_of_e2_vector.get_local() + + vec_dd = np.zeros(3); vec_dd2 = np.zeros(3); vec_dd3 = np.zeros(3); vec_dd4 = np.zeros(3); + + Qepi = np.zeros((total_dd,3)); Qrv = np.zeros((total_dd,3)); Qlv = np.zeros((total_dd,3)); + Qendo = np.zeros((total_dd,3)) + Qfiber = np.zeros((total_dd,3)) + + e0_epi = np.zeros(total_dd); e1_epi = np.zeros(total_dd); e2_epi = np.zeros(total_dd); + e0_rv = np.zeros(total_dd); e1_rv = np.zeros(total_dd); e2_rv = np.zeros(total_dd); + e0_lv = np.zeros(total_dd); e1_lv = np.zeros(total_dd); e2_lv = np.zeros(total_dd); + check = np.zeros(total_dd); check2 = np.zeros(total_dd); + ds = np.zeros(total_dd/3); al_s = np.zeros(total_dd/3); b_s = np.zeros(total_dd/3); + al_w = np.zeros(total_dd/3); b_w = np.zeros(total_dd/3); + + e0_endo = np.zeros(total_dd); e1_endo = np.zeros(total_dd); e2_endo = np.zeros(total_dd); + + + # Open MTV fiber and sheet files + if( MPI.rank(mpi_comm_world()) == 0): + + if(mtvfiberfilename): + mtvfiberfile = open(mtvfiberfilename, 'w') + print >>mtvfiberfile, total_dd/3, 10 + + + if(mtvsheetfilename): + mtvsheetfile = open(mtvsheetfilename, 'w') + print >>mtvsheetfile, total_dd/3 + + + for x_dof, y_dof, z_dof, scl in zip(x_dofs, y_dofs, z_dofs, scalar_dof): + + + if(abs(rv[scl]) < 1e-9 and abs(rv[scl] + lv[scl]) < 1e-9): + ds[scl] = 0.0 + else: + ds[scl] = rv[scl]/(lv[scl]+rv[scl]) + + + pt = Point(np.array([Sdof_coordinates[scl][0], Sdof_coordinates[scl][1], Sdof_coordinates[scl][2]])) + meshid = mesh.bounding_box_tree().compute_first_collision(pt) + + al_endo = lv_fiber_angle[0]; b_endo = lv_sheet_angle[0]; + al_epi = lv_fiber_angle[1]; b_epi = lv_sheet_angle[1]; + + if matid is not None: + if(matid.array()[meshid] == septummatid): + al_endo = septum_fiber_angle[0]; b_endo = septum_sheet_angle[0]; + al_epi = septum_fiber_angle[1]; b_epi = septum_sheet_angle[1]; + elif(matid.array()[meshid] == rvmatid): + al_endo = rv_fiber_angle[0]; b_endo = rv_sheet_angle[0]; + al_epi = rv_fiber_angle[1]; b_epi = rv_sheet_angle[1]; + + + al_s[scl] = al_endo*(1 - ds[scl]) - al_endo*ds[scl]; b_s[scl] = b_endo*(1 - ds[scl]) - b_endo*ds[scl]; + al_w[scl] = al_endo*(1 - epi[scl]) + al_epi*epi[scl]; b_w[scl] = b_endo*(1 - epi[scl]) + b_epi*epi[scl]; + + vec_dd[0] = dd[x_dof]; vec_dd[1] = dd[y_dof]; vec_dd[2] = dd[z_dof]; + vec_dd2[0] = dd2[x_dof]; vec_dd2[1] = dd2[y_dof]; vec_dd2[2] = dd2[z_dof]; + vec_dd3[0] = dd3[x_dof]; vec_dd3[1] = dd3[y_dof]; vec_dd3[2] = dd3[z_dof]; + vec_dd4[0] = dd4[x_dof]; vec_dd4[1] = dd4[y_dof]; vec_dd4[2] = dd4[z_dof]; + + + Qlv[c:c+3][0:3]= axisf(vec_dd4, -1.0*vec_dd2); + Qlv[c:c+3][0:3] = orto3(Qlv[c:c+3][0:3], cnt); + Qlv[c:c+3][0:3]= orient(Qlv[c:c+3][0:3], al_s[scl], b_s[scl]) + + + e0_lv[x_dof] = Qlv[c][0]; e0_lv[y_dof] = Qlv[c+1][0]; e0_lv[z_dof] = Qlv[c+2][0]; + e1_lv[x_dof] = Qlv[c][1]; e1_lv[y_dof] = Qlv[c+1][1]; e1_lv[z_dof] = Qlv[c+2][1]; + e2_lv[x_dof] = Qlv[c][2]; e2_lv[y_dof] = Qlv[c+1][2]; e2_lv[z_dof] = Qlv[c+2][2]; + + Qrv[c:c+3][0:3] = axisf(vec_dd4, -1.0*vec_dd3); + Qrv[c:c+3][0:3] = orto3(Qrv[c:c+3][0:3], cnt); + Qrv[c:c+3][0:3]= orient(Qrv[c:c+3][0:3], -al_s[scl], -b_s[scl]); + + e0_rv[x_dof] = Qrv[c][0]; e0_rv[y_dof] = Qrv[c+1][0]; e0_rv[z_dof] = Qrv[c+2][0]; + e1_rv[x_dof] = Qrv[c][1]; e1_rv[y_dof] = Qrv[c+1][1]; e1_rv[z_dof] = Qrv[c+2][1]; + e2_rv[x_dof] = Qrv[c][2]; e2_rv[y_dof] = Qrv[c+1][2]; e2_rv[z_dof] = Qrv[c+2][2]; + + + #Qendo[c:c+3][0:3] = bislerp(Qlv[c:c+3][0:3], Qrv[c:c+3][0:3], ds[scl]) + Qendo[c:c+3][0:3] = my_bislerp(Qlv[c:c+3][0:3], Qrv[c:c+3][0:3], ds[scl]) + + e0_endo[x_dof] = Qendo[c][0]; e0_endo[y_dof] = Qendo[c+1][0]; e0_endo[z_dof] = Qendo[c+2][0]; + e1_endo[x_dof] = Qendo[c][1]; e1_endo[y_dof] = Qendo[c+1][1]; e1_endo[z_dof] = Qendo[c+2][1]; + e2_endo[x_dof] = Qendo[c][2]; e2_endo[y_dof] = Qendo[c+1][2]; e2_endo[z_dof] = Qendo[c+2][2]; + + + Qepi[c:c+3][0:3] = axisf(vec_dd4, vec_dd); + Qepi[c:c+3][0:3] = orto3(Qepi[c:c+3][0:3], cnt); + Qepi[c:c+3][0:3] = orient(Qepi[c:c+3][0:3], al_w[scl], b_w[scl]); + + e0_epi[x_dof] = Qepi[c][0]; e0_epi[y_dof] = Qepi[c+1][0]; e0_epi[z_dof] = Qepi[c+2][0]; + e1_epi[x_dof] = Qepi[c][1]; e1_epi[y_dof] = Qepi[c+1][1]; e1_epi[z_dof] = Qepi[c+2][1]; + e2_epi[x_dof] = Qepi[c][2]; e2_epi[y_dof] = Qepi[c+1][2]; e2_epi[z_dof] = Qepi[c+2][2]; + + #Qfiber[c:c+3][0:3] = bislerp(Qendo[c:c+3][0:3], Qepi[c:c+3][0:3], epi[scl]) + Qfiber[c:c+3][0:3] = my_bislerp(Qendo[c:c+3][0:3], Qepi[c:c+3][0:3], epi[scl]) + + e0_fiber[x_dof] = Qfiber[c][0]; e0_fiber[y_dof] = Qfiber[c+1][0]; e0_fiber[z_dof] = Qfiber[c+2][0]; + e1_fiber[x_dof] = Qfiber[c][1]; e1_fiber[y_dof] = Qfiber[c+1][1]; e1_fiber[z_dof] = Qfiber[c+2][1]; + e2_fiber[x_dof] = Qfiber[c][2]; e2_fiber[y_dof] = Qfiber[c+1][2]; e2_fiber[z_dof] = Qfiber[c+2][2]; + + + cnt = cnt + 1; + c = c + 3; + + if(isrotatept): + points = [(-Sdof_coordinates[scl][2]+maxz)/10.0, Sdof_coordinates[scl][1]/10.0, Sdof_coordinates[scl][0]/10.0] + fvectors = [-1.0*e0_fiber[z_dof], e0_fiber[y_dof], e0_fiber[x_dof]] + svectors = [-1.0*e2_fiber[z_dof], e2_fiber[y_dof], e2_fiber[x_dof]] + + else: + points = [Sdof_coordinates[scl][0], Sdof_coordinates[scl][1], Sdof_coordinates[scl][2]] + fvectors = [e0_fiber[x_dof], e0_fiber[y_dof], e0_fiber[z_dof]] + svectors = [e2_fiber[x_dof], e2_fiber[y_dof], e2_fiber[z_dof]] + + + #print >>mtvfiberfile, points[0], points[1], points[2], fvectors[0], fvectors[1], fvectors[2] + #print >>mtvsheetfile, points[0], points[1], points[2], svectors[0], svectors[1], svectors[2] + + + vtkoutfile = outdirectory+outfilename+"_e0_fiber" + func_of_e0_vector.set_local(e0_fiber) + func_of_e0_vector.apply("insert") + vtk_py.convertQuadDataToVTK(mesh, V, func_of_e0, vtkoutfile) + + vtkoutfile = outdirectory+outfilename+"_e1_fiber" + func_of_e1_vector.set_local(e1_fiber) + func_of_e1_vector.apply("insert") + vtk_py.convertQuadDataToVTK(mesh, V, func_of_e1, vtkoutfile) + + vtkoutfile = outdirectory+outfilename+"_e2_fiber" + func_of_e2_vector.set_local(e2_fiber) + func_of_e2_vector.apply("insert") + vtk_py.convertQuadDataToVTK(mesh, V, func_of_e2, vtkoutfile) + + if(MPI.rank(mpi_comm_world()) == 0): + print isrotatept + print outdirectory + outfilename + print "*******************************************************" + + if(isreturn): + + return func_of_e0, func_of_e1, func_of_e2 + +if (__name__ == "__main__"): + + parser = argparse.ArgumentParser() + parser.add_argument('--xml_folder', type=str, required=True) + parser.add_argument('--xml_meshfilename', type=str, required=True) + parser.add_argument('--xml_facetfilename', type=str, required=True) + parser.add_argument('--mtv_grid_directory', type=str, required=True) + parser.add_argument('--mtv_basename', type=str, required=True) + parser.add_argument('--isrotatept', type=bool, required=True) + parser.add_argument('--al_endo', type=float, required=True) + parser.add_argument('--al_epi', type=float, required=True) + parser.add_argument('--b_endo', type=float, required=True) + parser.add_argument('--b_epi', type=float, required=True) + args = parser.parse_args() + + print "************* Entering SetBiVFiber.py *****************" + + xmlmeshfilename = os.path.join(args.xml_folder, args.xml_meshfilename) + xmlfacetfilename = os.path.join(args.xml_folder, args.xml_facetfilename) + outdirectory = args.mtv_grid_directory + outfilename = args.mtv_basename + isrotatept = args.isrotatept + al_endo = args.al_endo + al_epi = args.al_epi + b_endo = args.b_endo + b_epi = args.b_epi + + mesh = Mesh(xmlmeshfilename) + boundaries = MeshFunction("size_t", mesh, xmlfacetfilename) + mtvfiberfilename = outdirectory+outfilename+"_fiber_rotated.axis" + mtvsheetfilename = outdirectory+outfilename+"_sheet_rotated.axis" + + SetBiVFiber(mesh, boundaries, mtvfiberfilename, mtvsheetfilename, al_endo, al_epi, b_endo, b_epi, isrotatept, outfilename, outdirectory) + diff --git a/vtk_py/SetBiVFiber_Quad_PyQ.pyc b/vtk_py/SetBiVFiber_Quad_PyQ.pyc new file mode 100644 index 0000000..1f6a2b9 Binary files /dev/null and b/vtk_py/SetBiVFiber_Quad_PyQ.pyc differ diff --git a/vtk_py/SlerpTestJ.py b/vtk_py/SlerpTestJ.py new file mode 100644 index 0000000..4de765b --- /dev/null +++ b/vtk_py/SlerpTestJ.py @@ -0,0 +1,170 @@ +import pyquaternion as pyq +import numpy as np +import pdb + +def bislerp(Qa, Qb, t): + + Qa_M = mat3([Qa[0,0], Qa[0,1], Qa[0,2], Qa[1,0], Qa[1,1], Qa[1,2], Qa[2,0], Qa[2,1], Qa[2,2]]) + Qb_M = mat3([Qb[0,0], Qb[0,1], Qb[0,2], Qb[1,0], Qb[1,1], Qb[1,2], Qb[2,0], Qb[2,1], Qb[2,2]]) + qa = quat(Qa_M) + qb = quat(Qb_M) + + val = np.zeros(8) + quat_i = quat(0,1,0,0) + quat_j = quat(0,0,1,0) + quat_k = quat(0,0,0,1) + quat_array = [qa, -qa, qa*quat_i, -qa*quat_i, qa*quat_j, -qa*quat_j, qa*quat_k, -qa*quat_k] + cnt = 0 + for qt in quat_array: + val[cnt] = qt.dot(qb) + cnt = cnt + 1 + + qt = quat_array[val.argmax(axis=0)] + + if(t < 0): + t = 0.0 + + qm = slerp(t, qt, qb) + qm = qm.normalize() + Qm_M = qm.toMat3() + Qm = [[Qm_M[0,0], Qm_M[0,1], Qm_M[0,2]], [Qm_M[1,0], Qm_M[1,1], Qm_M[1,2]], [Qm_M[2,0], Qm_M[2,1], Qm_M[2,2]]] + + return Qm + + +def my_bislerp(Qa, Qb, t): + + #Qa_M = mat3([Qa[0,0], Qa[0,1], Qa[0,2], Qa[1,0], Qa[1,1], Qa[1,2], Qa[2,0], Qa[2,1], Qa[2,2]]) + #Qb_M = mat3([Qb[0,0], Qb[0,1], Qb[0,2], Qb[1,0], Qb[1,1], Qb[1,2], Qb[2,0], Qb[2,1], Qb[2,2]]) + #qa = quat(Qa_M) + #qb = quat(Qb_M) + + qa = pyq.Quaternion(matrix=Qa) + qb = pyq.Quaternion(matrix=Qb) + + + val = np.zeros(8) + #quat_i = quat(0,1,0,0) + #quat_j = quat(0,0,1,0) + #quat_k = quat(0,0,0,1) + + quat_i = pyq.Quaternion(0,1,0,0) + quat_j = pyq.Quaternion(0,0,1,0) + quat_k = pyq.Quaternion(0,0,0,1) + + quat_array = [qa, -qa, qa*quat_i, -qa*quat_i, qa*quat_j, -qa*quat_j, qa*quat_k, -qa*quat_k] + + + #print('My Quarternion NUMPY array {arr}'.format(arr=np.array(qa))) + #print('My Quarternion NUMPY array {arr}'.format(arr=np.array([qa[0], qa[1], qa[2], qa[3] ]) ) ) + + + cnt = 0 + qb_arr = np.array([qb[0], qb[1], qb[2], qb[3]]) + for qt in quat_array: + qt_arr = np.array([qt[0], qt[1], qt[2], qt[3]]) + val[cnt] = np.dot(qt_arr, qb_arr) + cnt = cnt + 1 + + print('calculated val array is :{arr}'.format(arr=val)) + qt = quat_array[val.argmax(axis=0)] + print('calculated val array is :{arr}'.format(arr=qt)) + + + + if(t < 0): + t = 0.0 + + #qm = slerp(t, qt, qb) + qm = pyq.Quaternion.slerp(qt, qb, t) + qm = qm.normalised + Qm_M = qm.rotation_matrix + + print('calculated val matrix is :{mat}'.format(mat=Qm_M)) + + #Qm = [[Qm_M[0,0], Qm_M[0,1], Qm_M[0,2]], [Qm_M[1,0], Qm_M[1,1], Qm_M[1,2]], [Qm_M[2,0], Qm_M[2,1], Qm_M[2,2]]] + + return Qm_M + + +def run_demo(): + #https://github.com/KieranWynn/pyquaternion + + # Create a quaternion representing a rotation of +90 degrees about positive y axis. + my_quaternion = pyq.Quaternion(axis=[0, 1, 0], degrees=90) + + my_vector = [0, 0, 4] + my_rotated_vector = my_quaternion.rotate(my_vector) + + print('\nBasic Rotation') + print('--------------') + print('My Vector: {}'.format(my_vector)) + print('Performing rotation of {angle} deg about {axis}'.format(angle=my_quaternion.degrees, axis=my_quaternion.axis)) + print('My Rotated Vector: {}'.format(my_rotated_vector)) + + # Create another quaternion representing no rotation at all + null_quaternion = pyq.Quaternion(axis=[0, 1, 0], angle=0) + + print('\nInterpolated Rotation') + print('---------------------') + + # The following will create a sequence of 9 intermediate quaternion rotation objects + for q in pyq.Quaternion.intermediates(null_quaternion, my_quaternion, 9, include_endpoints=True): + my_interpolated_point = q.rotate(my_vector) + print('My Interpolated Point: {point}\t(after rotation of {angle} deg about {axis})'.format( + point=my_interpolated_point, angle=round(q.degrees, 4), axis=q.axis + )) + + print('Done!') + +def run_tests(): + rotation = np.eye(3) + q = pyq.Quaternion(matrix=rotation) # Using 3x3 rotation matrix + print('My first Quaternion from matrix is: {quat}\t with angle {angle} and axis {axis}'.format( + quat=q, angle=q.degrees, axis=q.axis)) + + q1 = pyq.Quaternion.random() + print('My first Quaternion from matrix is: {quat}\t with angle {angle} and axis {axis}'.format( + quat=q1, angle=q1.degrees, axis=q1.axis)) + + q2 = pyq.Quaternion.random() + print('My second random Quaternion is: {quat}\t with angle {angle} and axis {axis}'.format( + quat=q2, angle=q2.degrees, axis=q2.axis)) + + q1_q2 = q1*q2 + print('My multiplied Quaternion is: {quat}\t with angle {angle} and axis {axis}'.format( + quat=q1_q2, angle=q1_q2.degrees, axis=q1_q2.axis)) + + q_interp = pyq.Quaternion.slerp(q1, q2, amount = 0.5) + print('My SLERP interpiolated Quaternion is: {quat}\t with angle {angle} and axis {axis}'.format( + quat=q_interp, angle=q_interp.degrees, axis=q_interp.axis)) + + q_interp_normalzied = q_interp.normalised + print('My normalized interpolated Quaternion is: {quat}\t with angle {angle} and axis {axis}'.format( + quat=q_interp_normalzied, angle=q_interp_normalzied.degrees, axis=q_interp_normalzied.axis)) + + q_interp_matrix = q_interp.rotation_matrix + print('My interpolated Quaternion in matrix form is: \n {quat}'.format( + quat=q_interp_matrix)) + + +if __name__ == "__main__": + + #run_demo() + #run_tests() + + q1 = pyq.Quaternion.random() + q1mat = q1.rotation_matrix + print('My roated Quaternion in matrix form is: \n {quat}'.format( + quat=q1mat)) + + q2 = pyq.Quaternion.random() + q2mat = q2.rotation_matrix + print('My rotated Quaternion in matrix form is: \n {quat}'.format( + quat=q2mat)) + + q_interp_mat = my_bislerp(q1mat, q2mat, 0.3) + print('My interpolated Quaternion in matrix form is: \n {quat}'.format( + quat=q_interp_mat)) + + pdb.set_trace() diff --git a/vtk_py/__init__.py b/vtk_py/__init__.py new file mode 100644 index 0000000..c346ebf --- /dev/null +++ b/vtk_py/__init__.py @@ -0,0 +1,90 @@ +from addFieldPrincipalDirections import * +from addLocalCylindricalDirections import * +from addLocalFiberOrientation import * +from addLocalFiberOrientation2 import * +from addLocalProlateSpheroidalDirections import * +from addMappingFromPointsToCells import * +from addSystolicStrains import * +from clipDomainForCutLVMesh import * +from clipSurfacesForCutLVMesh import * +from clipSurfacesForFullLVMesh import * +from clipheart_ugrid import * +from createFloatArray import * +from createIntArray import * +from exportDynaDeformationGradients import * +from findPointsInCell import * +from getABPointsFromBoundsAndCenter import * +from getABPointsFromTTTSectors import * +from getCellCenters import * +from mapCellDataToCellData import * +from mapPointDataToCellData import * +from readAbaqusDeformationGradients import * +from readAbaqusMesh import * +from readAbaqusStresses import * +from readDynaDeformationGradients import * +from readDynaDeformationGradients_vtk import * +from readDynaMesh import * +from readDynaMeshStructured import * +from readFiberOrientation import * +from readPData import * +from readSTL import * +from readUGrid import * +from readXMLImage import * +from readXMLPData import * +from readXMLUGrid import * +from readXMLPUGrid import * +from rotateSymmetricMatrix import * +from splitDomainBetweenEndoAndEpi import * +from writeFiberOrientationFileForAbaqus import * +from writeFiberOrientationFileForGNUPlot import * +from writePData import * +from writeSTL import * +from writeUGrid import * +from writeXMLImage import * +from writeXMLPData import * +from writeXMLUGrid import * +from transform_mesh_w_4x4mat import * +from transform_pdata import * +from sliceheart import * +from clean_pdata import * +from extract_slice_thickness import * +from clipheart import * +from clipSurfacesForCutLVMesh_PLY import * +from readPLY import * +from extract_slice_thickness_LVonly import * +from computeVolume import * +from computeRegionsForBiV import * +from getCellLocator import * +from CreateVertexFromPoint import * +from convertUGridtoPdata import * +from getcentroid import * +from createLVmesh import * +from computeLVthickness import * +from translate_mesh import * +#from translate_pdata import * +from convertCellDataToXML import * +from readMSHGrid import * +from addLocalFiberOrientation_infarct import * +from convertXMLMeshToUGrid import * +from extractFeNiCsBiVFacet import * +#from SetBiVFiber import * +#from SetBiVFiber_Quad import * +from SetBiVFiber_Quad_PyQ import * +from extractCellFromPData import * +from readVTI import * +from create_ellipsoidal_LV import * +from addLVfiber import * +from addLVfiber_LDRB import * +from convertQuadDataToVTK import * +from convertUGridToXMLMesh import * +from Set4ChamberDirection import * +from create_BiVmesh import * +from rotateUGrid import * +#from convertXMLMeshToUGrid2D import * +#from SetBiVFiber_Ce import * +from SetBiVFiber_J import * +#from SlerpTestJ import * +from rotatePData_w_axis import * +from convertPDataToXMLMesh import * +from extractUGridBasedOnThreshold import * +#from pyquaternion import * diff --git a/vtk_py/__init__.pyc b/vtk_py/__init__.pyc new file mode 100644 index 0000000..c3d426e Binary files /dev/null and b/vtk_py/__init__.pyc differ diff --git a/vtk_py/_q! b/vtk_py/_q! new file mode 100644 index 0000000..704c70f --- /dev/null +++ b/vtk_py/_q! @@ -0,0 +1,17 @@ +######################################################################## + +import vtk + +######################################################################## + +def writeXMLUGrid(ugrid, ugrid_file_name, verbose=True): + if (verbose): print 'Writing XML UGrid...' + + ugrid_writer = vtk.vtkUnstructuredGridWriter() + ugrid_writer.SetFileName(ugrid_file_name) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + ugrid_writer.SetInputData(ugrid) + else: + ugrid_writer.SetInput(ugrid) + ugrid_writer.Update() + ugrid_writer.Write() diff --git a/vtk_py/addFieldPrincipalDirections.py b/vtk_py/addFieldPrincipalDirections.py new file mode 100644 index 0000000..660c24b --- /dev/null +++ b/vtk_py/addFieldPrincipalDirections.py @@ -0,0 +1,99 @@ +######################################################################## + +import numpy +import vtk + +from mat_vec_tools import * +from createFloatArray import * + +######################################################################## + +def addFieldPrincipalDirections(ugrid_mesh, + field_name, + field_type="cell", + field_storage="vec", + verbose=True): + + if (verbose): print '*** addFieldPrincipalDirections ***' + + assert (field_type in ["point", "cell"]), "\"field_type\" must be \"point\" or \"cell\". Aborting." + assert (field_storage in ["vec", "Cmat", "Fmat"]), "\"field_storage\" must be \"vec\", \"Cmat\" or \"Fmat\". Aborting." + + if (field_type == "cell" ): nb_cells = ugrid_mesh.GetNumberOfCells() + elif (field_type == "point"): nb_cells = ugrid_mesh.GetNumberOfPoints() + + if (field_type == "cell" ): field = ugrid_mesh.GetCellData().GetArray(field_name) + elif (field_type == "point"): field = ugrid_mesh.GetPointData().GetArray(field_name) + + field_Lmin = createFloatArray(field_name+'_Lmin', 1, nb_cells) + field_Lmid = createFloatArray(field_name+'_Lmid', 1, nb_cells) + field_Lmax = createFloatArray(field_name+'_Lmax', 1, nb_cells) + + field_Vmin = createFloatArray(field_name+'_Vmin', 3, nb_cells) + field_Vmid = createFloatArray(field_name+'_Vmid', 3, nb_cells) + field_Vmax = createFloatArray(field_name+'_Vmax', 3, nb_cells) + + for num_cell in range(nb_cells): + if (field_storage == "vec" ): matrix = vec_col_to_mat_sym(field.GetTuple(num_cell)) + elif (field_storage == "Cmat"): matrix = numpy.reshape(field.GetTuple(num_cell), (3,3), order='C') + elif (field_storage == "Fmat"): matrix = numpy.reshape(field.GetTuple(num_cell), (3,3), order='F') + + if (numpy.linalg.norm(matrix) > 1e-6): + #if (verbose): print 'num_cell =', num_cell + + val, vec = numpy.linalg.eig(matrix) + #if (verbose): print 'val =', val + #if (verbose): print 'vec =', vec + idx = val.argsort() + val = val[idx] + vec = vec[:,idx] + #if (verbose): print 'val =', val + #if (verbose): print 'vec =', vec + + matrix_Lmin = [val[0]] + matrix_Lmid = [val[1]] + matrix_Lmax = [val[2]] + + matrix_Vmin = vec[:,0] + matrix_Vmid = vec[:,1] + matrix_Vmax = vec[:,2] + else: + matrix_Lmin = [0.] + matrix_Lmid = [0.] + matrix_Lmax = [0.] + matrix_Vmin = [0.]*3 + matrix_Vmid = [0.]*3 + matrix_Vmax = [0.]*3 + + field_Lmin.InsertTuple(num_cell, matrix_Lmin) + field_Lmid.InsertTuple(num_cell, matrix_Lmid) + field_Lmax.InsertTuple(num_cell, matrix_Lmax) + field_Vmin.InsertTuple(num_cell, matrix_Vmin) + field_Vmid.InsertTuple(num_cell, matrix_Vmid) + field_Vmax.InsertTuple(num_cell, matrix_Vmax) + + if (field_type == "cell"): + ugrid_mesh.GetCellData().AddArray(field_Lmin) + ugrid_mesh.GetCellData().AddArray(field_Lmid) + ugrid_mesh.GetCellData().AddArray(field_Lmax) + ugrid_mesh.GetCellData().AddArray(field_Vmin) + ugrid_mesh.GetCellData().AddArray(field_Vmid) + ugrid_mesh.GetCellData().AddArray(field_Vmax) + elif (field_type == "point"): + ugrid_mesh.GetPointData().AddArray(field_Lmin) + ugrid_mesh.GetPointData().AddArray(field_Lmid) + ugrid_mesh.GetPointData().AddArray(field_Lmax) + ugrid_mesh.GetPointData().AddArray(field_Vmin) + ugrid_mesh.GetPointData().AddArray(field_Vmid) + ugrid_mesh.GetPointData().AddArray(field_Vmax) + +if (__name__ == "__main__"): + assert (len(sys.argv) in [3,4,5]), "Number of arguments must be 2, 3 or 4. Aborting." + ugrid_mesh = readUGrid(sys.argv[1]) + if (len(sys.argv) == 2): + addFieldPrincipalDirections(ugrid_mesh, sys.argv[2]) + elif (len(sys.argv) == 3): + addFieldPrincipalDirections(ugrid_mesh, sys.argv[2], sys.argv[3]) + elif (len(sys.argv) == 4): + addFieldPrincipalDirections(ugrid_mesh, sys.argv[2], sys.argv[3], sys.argv[4]) + writeUGrid(ugrid_mesh, sys.argv[1]) diff --git a/vtk_py/addFieldPrincipalDirections.pyc b/vtk_py/addFieldPrincipalDirections.pyc new file mode 100644 index 0000000..0702162 Binary files /dev/null and b/vtk_py/addFieldPrincipalDirections.pyc differ diff --git a/vtk_py/addLVfiber.py b/vtk_py/addLVfiber.py new file mode 100644 index 0000000..a64f83d --- /dev/null +++ b/vtk_py/addLVfiber.py @@ -0,0 +1,132 @@ +from dolfin import * +import vtk as vtk +from vtk_py import * + +def addLVfiber(mesh, V, casename, endo_angle, epi_angle, casedir, isepiflip, isendoflip, isapexflip=False): + + + fiberV = Function(V) + sheetV = Function(V) + sheetnormV = Function(V) + cV = Function(V) + lV = Function(V) + rV = Function(V) + + ugrid=vtk_py.convertXMLMeshToUGrid(mesh) + + pdata = vtk_py.convertUGridtoPdata(ugrid) + + C = vtk_py.getcentroid(pdata) + if(isapexflip): + ztop = pdata.GetBounds()[4] + C = [C[0], C[1], ztop+0.05] + clippedheart = vtk_py.clipheart(pdata, C, [0,0,-1], True) + else: + ztop = pdata.GetBounds()[5] + C = [C[0], C[1], ztop-0.05] + clippedheart = vtk_py.clipheart(pdata, C, [0,0,1], True) + epi, endo= vtk_py.splitDomainBetweenEndoAndEpi(clippedheart) + + cleanepipdata = vtk.vtkCleanPolyData() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + cleanepipdata.SetInputData(epi) + else: + cleanepipdata.SetInput(epi) + cleanepipdata.Update() + pdata_epi = cleanepipdata.GetOutput() + + cleanendopdata = vtk.vtkCleanPolyData() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + cleanendopdata.SetInputData(endo) + else: + cleanendopdata.SetInput(endo) + cleanendopdata.Update() + pdata_endo = cleanendopdata.GetOutput() + + L_epi = pdata_epi.GetBounds()[5] - pdata_epi.GetBounds()[4] + L_endo = pdata_endo.GetBounds()[5] - pdata_endo.GetBounds()[4] + + if(L_endo > L_epi): + pdata_epi = temp + pdata_epi = pdata_endo + pdata_endo = temp + + + # Quad points + gdim = mesh.geometry().dim() + xdofmap = V.sub(0).dofmap().dofs() + ydofmap = V.sub(1).dofmap().dofs() + zdofmap = V.sub(2).dofmap().dofs() + + if(dolfin.dolfin_version() != '1.6.0'): + xq = V.tabulate_dof_coordinates().reshape((-1, gdim)) + xq0 = xq[xdofmap] + else: + xq = V.dofmap().tabulate_all_coordinates(mesh).reshape((-1, gdim)) + xq0 = xq[xdofmap] + + # Create an unstructured grid of Gauss Points + points = vtk.vtkPoints() + vertices = vtk.vtkCellArray() + ugrid = vtk.vtkUnstructuredGrid() + cnt = 0; + for pt in xq0: + points.InsertNextPoint([pt[0], pt[1], pt[2]]) + vertex = vtk.vtkVertex() + vertex.GetPointIds().SetId(0, cnt) + vertices.InsertNextCell(vertex) + cnt += 1 + + ugrid.SetPoints(points) + ugrid.SetCells(0, vertices) + + CreateVertexFromPoint(ugrid) + addLocalProlateSpheroidalDirections(ugrid, pdata_endo, pdata_epi, type_of_support="cell", epiflip=isepiflip, endoflip=isendoflip, apexflip=isapexflip) + addLocalFiberOrientation(ugrid, endo_angle, epi_angle) + + fiber_vector = ugrid.GetCellData().GetArray("fiber vectors") + sheet_vector = ugrid.GetCellData().GetArray("sheet vectors") + sheetnorm_vector = ugrid.GetCellData().GetArray("sheet normal vectors") + + eCC_vector = ugrid.GetCellData().GetArray("eCC") + eLL_vector = ugrid.GetCellData().GetArray("eLL") + eRR_vector = ugrid.GetCellData().GetArray("eRR") + + cnt = 0 + for pt in xq0: + + fvec = fiber_vector.GetTuple(cnt) + svec = sheet_vector.GetTuple(cnt) + nvec = sheetnorm_vector.GetTuple(cnt) + + cvec = eCC_vector.GetTuple(cnt) + lvec = eLL_vector.GetTuple(cnt) + rvec = eRR_vector.GetTuple(cnt) + + fvecnorm = sqrt(fvec[0]**2 + fvec[1]**2 + fvec[2]**2) + svecnorm = sqrt(svec[0]**2 + svec[1]**2 + svec[2]**2) + nvecnorm = sqrt(nvec[0]**2 + nvec[1]**2 + nvec[2]**2) + + if(abs(fvecnorm - 1.0) > 1e-7 or abs(svecnorm - 1.0) > 1e-6 or abs(nvecnorm - 1.0) > 1e-7): + print fvecnorm + print svecnorm + print nvecnorm + + #print xdofmap[cnt], ydofmap[cnt], zdofmap[cnt] + fiberV.vector()[xdofmap[cnt]] = fvec[0]; fiberV.vector()[ydofmap[cnt]] = fvec[1]; fiberV.vector()[zdofmap[cnt]] = fvec[2]; + sheetV.vector()[xdofmap[cnt]] = svec[0]; sheetV.vector()[ydofmap[cnt]] = svec[1]; sheetV.vector()[zdofmap[cnt]] = svec[2]; + sheetnormV.vector()[xdofmap[cnt]] = nvec[0]; sheetnormV.vector()[ydofmap[cnt]] = nvec[1]; sheetnormV.vector()[zdofmap[cnt]] = nvec[2]; + + cV.vector()[xdofmap[cnt]] = cvec[0]; cV.vector()[ydofmap[cnt]] = cvec[1]; cV.vector()[zdofmap[cnt]] = cvec[2]; + lV.vector()[xdofmap[cnt]] = lvec[0]; lV.vector()[ydofmap[cnt]] = lvec[1]; lV.vector()[zdofmap[cnt]] = lvec[2]; + rV.vector()[xdofmap[cnt]] = rvec[0]; rV.vector()[ydofmap[cnt]] = rvec[1]; rV.vector()[zdofmap[cnt]] = rvec[2]; + + + cnt += 1 + + + writeXMLUGrid(ugrid, "fiber.vtu") + + return fiberV, sheetV, sheetnormV, cV, lV, rV + + diff --git a/vtk_py/addLVfiber.pyc b/vtk_py/addLVfiber.pyc new file mode 100644 index 0000000..c08e4c1 Binary files /dev/null and b/vtk_py/addLVfiber.pyc differ diff --git a/vtk_py/addLVfiber_LDRB.py b/vtk_py/addLVfiber_LDRB.py new file mode 100644 index 0000000..e5fe57e --- /dev/null +++ b/vtk_py/addLVfiber_LDRB.py @@ -0,0 +1,470 @@ +######################################################################## +import argparse +from mpi4py import MPI as pyMPI +import numpy as np +#from thLib import quat +import sys +import os +from dolfin import * +from sympy import Symbol, nsolve +import math +from scipy import linalg +from scipy import optimize + +import vtk_py as vtk_py + +import pyquaternion as pyq +import pdb + + +######################################################################## + +def addLVfiber_LDRB(param): + + mesh = param["mesh"] + boundaries = param["facetboundaries"] + + epiid = param["epiid"] if ("epiid" in param) else 2 + lvid = param["lvid"] if ("lvid" in param) else 3 + outdirectory = param["outdirectory"] if ("outdirectory" in param) else "" + isrotatept = param["isrotatept"] if ("isrotatept" in param) else False + isreturn = param["isreturn"] if ("isreturn" in param) else True + isscaling = param["isscaling"] if ("isscaling" in param) else False + outfilename = param["outfilename"] if ("outfilename" in param) else "fiber" + degree = param["degree"] if ("degree" in param) else 2 + + lv_fiber_angle = np.array(param["LV_fiber_angle"])*math.pi/180 if ("LV_fiber_angle" in param) else np.array([60, -60])*math.pi/180 + lv_sheet_angle = np.array(param["LV_sheet_angle"])*math.pi/180 if ("LV_sheet_angle" in param) else np.array([0.1, -0.1])*math.pi/180 + + comm = mesh.mpi_comm().tompi4py() + + minz = comm.allreduce(np.amin(mesh.coordinates()[:,2]), op=pyMPI.MIN) + maxz = comm.allreduce(np.amax(mesh.coordinates()[:,2]), op=pyMPI.MAX) + + def right_boundary(x): + return x[2] < minz+0.5 + + # Function that solves the Laplace equation and and calculates the gradient of the solution + def lap(Me, boud, par,op, filename): + + set_log_level(40) + parameters["form_compiler"]["quadrature_degree"] = degree + parameters["form_compiler"]["representation"] = 'quadrature' + + epi=epiid; lv=lvid; + # Create mesh and define function space + mesh = Me + V = FunctionSpace(mesh, FiniteElement("Lagrange", mesh.ufl_cell(), 2)) + SQuad = FunctionSpace(mesh, FiniteElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + + y = mesh.coordinates() + sa = y.shape + ttt = y[:, 2].min() + cord = np.argwhere(y == ttt); + point = y[cord[0,0],:] + #print sa, cord, point + u0 = Constant(0.0) + if op == 1: + bc =[ DirichletBC(V, u0, right_boundary), DirichletBC(V, 1, boud, 4)] + # Define boundary conditions + else: + bc = [DirichletBC(V, par[0], boud, lv), DirichletBC(V, par[1], boud, epi )] + + # Define variational problem + u = TrialFunction(V) + v = TestFunction(V) + f = Constant(0) + a = inner(nabla_grad(u), nabla_grad(v))*dx + L = f*v*dx + + # Compute solution + u = Function(V) + solve(a == L, u, bc)#, solver_parameters={"linear_solver": "petsc"}) + u_a = u.vector().array() + u_a_quad = project(u, SQuad).vector().get_local()#, solver_type="petsc").vector().array() + + + # Compute gradient + V_g = FunctionSpace(mesh, VectorElement("Lagrange", mesh.ufl_cell(), 2)) + VQuad = FunctionSpace(mesh, VectorElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + v = TestFunction(V_g) + w = TrialFunction(V_g) + + a = inner(w, v)*dx + L = inner(grad(u), v)*dx + grad_u = Function(V_g) + solve(a == L, grad_u)#, solver_parameters={"linear_solver": "petsc"}) + grad_u_quad = project(grad_u, VQuad)#, solver_type="petsc") + grad_u.rename('grad_u', 'continuous gradient field') + grad_ua_quad = grad_u_quad.vector().get_local()#.array() + + # Dump solution to file in VTK format + newfilename = filename + '.pvd' + file1= File(newfilename) + #file1<< u + + newfilename = filename + 'grad.pvd' + file2 = File(newfilename) + #file2 << grad_u + + return u_a_quad, grad_ua_quad + + + + # Function to calculate the lenght of the vector + + def len_vec(vec): + l = (vec[0]**2 + vec[1]**2 + vec[2]**2)**0.5 + return l + + + #newfilename = filename + 'grad.pvd' + #file2 = File(newfilename) + #file2 << grad_u + + # Hold plot + #interactive() + #return u_a_quad, grad_ua_quad + + ################################################################################################## + # Function to calculate the orthogonal axis using the gradients calculated in the previous step + ################################################################################################### + def L1(e0, v0): + + L1x = (v0[0] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[0])**2 + L1y = (v0[1] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[1])**2 + L1z = (v0[2] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[2])**2 + + return (L1x + L1y + L1z)**0.5; + + def P(e0, v0): + + P1x = v0[0] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[0] + P1y = v0[1] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[1] + P1z = v0[2] - (e0[0]*v0[0] + e0[1]*v0[1] + e0[2]*v0[2])*e0[2] + + return [P1x, P1y, P1z]; + + def function_e0(e0, v0, e1): + + f = [L1(e0,v0)*e0[0] - (e1[1]*P(e0,v0)[2] - e1[2]*P(e0,v0)[1]), + L1(e0,v0)*e0[1] - (e1[2]*P(e0,v0)[0] - e1[0]*P(e0,v0)[2]), + L1(e0,v0)*e0[2] - (e1[0]*P(e0,v0)[1] - e1[1]*P(e0,v0)[0])] + + return f; + + + def axisf(vec1, vec2): + + len_vec2 = len_vec(vec2); len_vec1 = len_vec(vec1); + e1 = vec1/len_vec1; ini_e2 = vec2/len_vec2; + ini_e0 = np.cross(e1, ini_e2) + + + e0 = np.zeros(3); e2 = np.zeros(3); + + # Solve using numerical + def function_wrap(e0): + return function_e0(e0, vec2, e1) + + sol = optimize.root(function_wrap, [ini_e0[0], ini_e0[1], ini_e0[2]], method='hybr') + e0[0] = sol.x[0]; e0[1] = sol.x[1]; e0[2] = sol.x[2]; + e2 = P(e0, vec2); + len_e2 = len_vec(e2) + e2[0] = e2[0]/len_e2; e2[1] = e2[1]/len_e2; e2[2] = e2[2]/len_e2; + + Q = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + + + return Q + + + ################################################################################################# + #Function to ensure the that the axis are orthogonal + ################################################################################################# + def orto(Q, cnt): + e0 = np.zeros(3); e1 = np.zeros(3); e2 = np.zeros(3); + e0[0] = Q[0][0]; e0[1] = Q[1][0]; e0[2] = Q[2][0]; + e1[0] = Q[0][1]; e1[1] = Q[1][1]; e1[2] = Q[2][1]; + e2[0] = Q[0][2]; e2[1] = Q[1][2]; e2[2] = Q[2][2]; + e0x = Symbol('e0x'); e0y = Symbol('e0y') ; e0z = Symbol('e0z'); e2x = Symbol('e2x'); e2y = Symbol('e2y') ; e2z = Symbol('e2z'); + + + try: + + aa = nsolve( [ e0x - e1[1]*e2z + e1[2]*e2y, e0y - e1[2]*e2x + e1[0]*e2z, e0z - e1[0]*e2y + e1[1]*e2x, e1[0] - e2y*e0z + e2z*e0y, e1[1] - e2z*e0x + e2x*e0z, e1[2] - e2x*e0y + e2y*e0x ], [ e0x, e0y, e0z, e2x, e2y, e2z ],[e0[0], e0[1], e0[2], e2[0], e2[1],e2[2] ]) + + + + e0[0] = aa[0]; e0[1] = aa[1]; e0[2] = aa[2]; + e2[0] = aa[3]; e2[1] = aa[4]; e2[2] = aa[5]; + Qa = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + + except ZeroDivisionError as detail: + print 'Handling run-time error:', detail + Qa = Q + f = quat.rotmat2quat(Qa) + outfile = open("quat.txt", "w") + print >>outfile, cnt, " ", f + return Qa + + + def orto3(Q, cnt): + + Q2 = np.dot(np.transpose(Q),Q) + Q2inv = np.linalg.inv(Q2) + sqrtQ2 = linalg.sqrtm(Q2inv) + Qa = np.dot(Q,sqrtQ2) + + return Qa + + ################################################################################################# + #Function to ensure the that the axis are orthogonal but this one is not working prorperly + ################################################################################################# + + def orto2(Q): + e0 = np.zeros(3); e1 = np.zeros(3); e2 = np.zeros(3); + e0[0] = Q[0][0]; e0[1] = Q[1][0]; e0[2] = Q[2][0]; + e1[0] = Q[0][1]; e1[1] = Q[1][1]; e1[2] = Q[2][1]; + e2[0] = Q[0][2]; e2[1] = Q[1][2]; e2[2] = Q[2][2]; + + while np.dot(e0, e1) + np.dot(e0, e2) + np.dot(e1, e2) > 10e-30: + e2 = np.cross(e0, e1); + e0 = np.cross(e1, e2); + Qa = np.array([[e0[0], e1[0], e2[0] ],[ e0[1], e1[1], e2[1]],[ e0[2], e1[2], e2[2]]]) + return Qa + + ############################################################################################## + #Function 3 - This function rotates the axis calculated in the previous steps + ############################################################################################## + + def orient(Q, al, bt): + arr1 =np.array( [[np.cos(al), -np.sin(al), 0 ],[np.sin(al), np.cos(al), 0],[0, 0, 1]]); + arr2 = np.array([[1, 0, 0],[0, np.cos(bt), np.sin(bt) ],[0, -np.sin(bt), np.cos(bt) ]]); + out = np.dot(Q, arr1, arr2) + return out + + ################################################################################################## + #Function 4 - This function calculates quarternions and interpolates these quarternions + ################################################################################################# + + def bislerp(Qa, Qb, t): + + Qa_M = mat3([Qa[0,0], Qa[0,1], Qa[0,2], Qa[1,0], Qa[1,1], Qa[1,2], Qa[2,0], Qa[2,1], Qa[2,2]]) + Qb_M = mat3([Qb[0,0], Qb[0,1], Qb[0,2], Qb[1,0], Qb[1,1], Qb[1,2], Qb[2,0], Qb[2,1], Qb[2,2]]) + qa = quat(Qa_M) + qb = quat(Qb_M) + + val = np.zeros(8) + quat_i = quat(0,1,0,0) + quat_j = quat(0,0,1,0) + quat_k = quat(0,0,0,1) + quat_array = [qa, -qa, qa*quat_i, -qa*quat_i, qa*quat_j, -qa*quat_j, qa*quat_k, -qa*quat_k] + cnt = 0 + for qt in quat_array: + val[cnt] = qt.dot(qb) + cnt = cnt + 1 + + qt = quat_array[val.argmax(axis=0)] + + if(t < 0): + t = 0.0 + + + qm = slerp(t, qt, qb) + qm = qm.normalize() + Qm_M = qm.toMat3() + Qm = [[Qm_M[0,0], Qm_M[0,1], Qm_M[0,2]], [Qm_M[1,0], Qm_M[1,1], Qm_M[1,2]], [Qm_M[2,0], Qm_M[2,1], Qm_M[2,2]]] + + return Qm + + def my_bislerp(Qa, Qb, t): + + qa = pyq.Quaternion(matrix=Qa) + qb = pyq.Quaternion(matrix=Qb) + + + val = np.zeros(8) + + quat_i = pyq.Quaternion(0,1,0,0) + quat_j = pyq.Quaternion(0,0,1,0) + quat_k = pyq.Quaternion(0,0,0,1) + + quat_array = [qa, -qa, qa*quat_i, -qa*quat_i, qa*quat_j, -qa*quat_j, qa*quat_k, -qa*quat_k] + + cnt = 0 + qb_arr = np.array([qb[0], qb[1], qb[2], qb[3]]) + + for qt in quat_array: + #val[cnt] = qt.dot(qb) + qt_arr = np.array([qt[0], qt[1], qt[2], qt[3]]) + val[cnt] = np.dot(qt_arr, qb_arr) + cnt = cnt + 1 + + qt = quat_array[val.argmax(axis=0)] + + if(t < 0): + t = 0.0 + + #qm = slerp(t, qt, qb) + qm = pyq.Quaternion.slerp(qt, qb, t) + qm = qm.normalised + Qm_M = qm.rotation_matrix + + return Qm_M + + + + ################################################################################################# + ######Generating results and using the functions ########## + ################################################################################################# + # DOF map + parameters["form_compiler"]["quadrature_degree"] = degree + parameters["form_compiler"]["representation"] = 'quadrature' + + V = FunctionSpace(mesh, VectorElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + S = FunctionSpace(mesh, FiniteElement("Quadrature", mesh.ufl_cell(), degree=degree, quad_scheme="default")) + + dof_coordinates = V.tabulate_dof_coordinates() + Sdof_coordinates = S.tabulate_dof_coordinates() + n = V.dim() + d = mesh.geometry().dim() + dof_coordinates.resize((n, d)) + Sdof_coordinates.resize((n,d)) + + x_my_first, x_my_last = V.sub(0).dofmap().ownership_range() + x_dofs = np.arange(0, x_my_last-x_my_first, d) + y_dofs = np.arange(1, x_my_last-x_my_first, d) + z_dofs = np.arange(2, x_my_last-x_my_first, d) + + + jj = np.array([ 1, 1, 1] ); hh = np.array([1, 1, 1]); + + + ####### Solving the poisson equation ############ + + # case 1) epi -> u = 0 and rv/lv -> u = 1 + + if(MPI.rank(mpi_comm_world()) == 0): + print "Solve Poisson Eq. 1, epi -> u = 0 and rv/lv -> u = 1" + par1 = [0, 1, 0]; epi, dd = lap(mesh, boundaries, par1, 0, 'phi_epi') + + #total_dd = comm.allreduce(len(dd), op=pyMPI.SUM) + #num_of_nodes = total_dd/3 + #scalar_array = np.zeros(num_of_nodes) + #scalar_dof = S.dofmap().dofs() + + total_dd = len(dd) + S_my_first, S_my_last = S.dofmap().ownership_range() + scalar_dof = filter(lambda dof: S.dofmap().local_to_global_index(dof) not in S.dofmap().local_to_global_unowned(), + xrange(S_my_last-S_my_first)) + + #case 4) from the top to the bottom + + if(MPI.rank(mpi_comm_world()) == 0): + print "Solve Poisson Eq. 4, from the top to the bottom" + par1 = [0, 1, 0]; b, dd4 = lap(mesh, boundaries, par1, 1, 'phi_ab') + + + + # Start calculating the fiber orientation + cnt = 0; c = 0; + vector_array = np.zeros(V.dim()) + + func_of_vector = Function(V); + func_of_scalar = Function(S); + + func_of_e0 = Function(V); + func_of_e1 = Function(V); + func_of_e2 = Function(V); + + func_of_e0_vector = func_of_e0.vector() + func_of_e1_vector = func_of_e1.vector() + func_of_e2_vector = func_of_e2.vector() + + e0_fiber = func_of_e0_vector.get_local() + e1_fiber = func_of_e1_vector.get_local() + e2_fiber = func_of_e2_vector.get_local() + + vec_dd = np.zeros(3); vec_dd2 = np.zeros(3); vec_dd3 = np.zeros(3); vec_dd4 = np.zeros(3); + + Qepi = np.zeros((total_dd,3)); Qlv = np.zeros((total_dd,3)); + Qendo = np.zeros((total_dd,3)) + Qfiber = np.zeros((total_dd,3)) + + e0_epi = np.zeros(total_dd); e1_epi = np.zeros(total_dd); e2_epi = np.zeros(total_dd); + e0_lv = np.zeros(total_dd); e1_lv = np.zeros(total_dd); e2_lv = np.zeros(total_dd); + check = np.zeros(total_dd); check2 = np.zeros(total_dd); + ds = np.zeros(total_dd/3); al_s = np.zeros(total_dd/3); b_s = np.zeros(total_dd/3); + al_w = np.zeros(total_dd/3); b_w = np.zeros(total_dd/3); + + e0_endo = np.zeros(total_dd); e1_endo = np.zeros(total_dd); e2_endo = np.zeros(total_dd); + + + for x_dof, y_dof, z_dof, scl in zip(x_dofs, y_dofs, z_dofs, scalar_dof): + + pt = Point(np.array([Sdof_coordinates[scl][0], Sdof_coordinates[scl][1], Sdof_coordinates[scl][2]])) + meshid = mesh.bounding_box_tree().compute_first_collision(pt) + + al_endo = lv_fiber_angle[0]; b_endo = lv_sheet_angle[0]; + al_epi = lv_fiber_angle[1]; b_epi = lv_sheet_angle[1]; + + al_w[scl] = al_endo*(1 - epi[scl]) + al_epi*epi[scl]; b_w[scl] = b_endo*(1 - epi[scl]) + b_epi*epi[scl]; + + vec_dd[0] = dd[x_dof]; vec_dd[1] = dd[y_dof]; vec_dd[2] = dd[z_dof]; + vec_dd4[0] = dd4[x_dof]; vec_dd4[1] = dd4[y_dof]; vec_dd4[2] = dd4[z_dof]; + + Qepi[c:c+3][0:3] = axisf(vec_dd4, vec_dd); + Qepi[c:c+3][0:3] = orto3(Qepi[c:c+3][0:3], cnt); + Qepi[c:c+3][0:3] = orient(Qepi[c:c+3][0:3], al_w[scl], b_w[scl]); + + e0_epi[x_dof] = Qepi[c][0]; e0_epi[y_dof] = Qepi[c+1][0]; e0_epi[z_dof] = Qepi[c+2][0]; + e1_epi[x_dof] = Qepi[c][1]; e1_epi[y_dof] = Qepi[c+1][1]; e1_epi[z_dof] = Qepi[c+2][1]; + e2_epi[x_dof] = Qepi[c][2]; e2_epi[y_dof] = Qepi[c+1][2]; e2_epi[z_dof] = Qepi[c+2][2]; + + Qfiber[c:c+3][0:3] = Qepi[c:c+3][0:3] + + e0_fiber[x_dof] = Qfiber[c][0]; e0_fiber[y_dof] = Qfiber[c+1][0]; e0_fiber[z_dof] = Qfiber[c+2][0]; + e1_fiber[x_dof] = Qfiber[c][1]; e1_fiber[y_dof] = Qfiber[c+1][1]; e1_fiber[z_dof] = Qfiber[c+2][1]; + e2_fiber[x_dof] = Qfiber[c][2]; e2_fiber[y_dof] = Qfiber[c+1][2]; e2_fiber[z_dof] = Qfiber[c+2][2]; + + cnt = cnt + 1; + c = c + 3; + + if(isrotatept): + points = [(-Sdof_coordinates[scl][2]+maxz)/10.0, Sdof_coordinates[scl][1]/10.0, Sdof_coordinates[scl][0]/10.0] + fvectors = [-1.0*e0_fiber[z_dof], e0_fiber[y_dof], e0_fiber[x_dof]] + svectors = [-1.0*e2_fiber[z_dof], e2_fiber[y_dof], e2_fiber[x_dof]] + + else: + points = [Sdof_coordinates[scl][0], Sdof_coordinates[scl][1], Sdof_coordinates[scl][2]] + fvectors = [e0_fiber[x_dof], e0_fiber[y_dof], e0_fiber[z_dof]] + svectors = [e2_fiber[x_dof], e2_fiber[y_dof], e2_fiber[z_dof]] + + + vtkoutfile = outfilename+"_e0_fiber" + func_of_e0_vector.set_local(e0_fiber) + func_of_e0_vector.apply("insert") + vtk_py.convertQuadDataToVTK(mesh, V, func_of_e0, vtkoutfile, outdirectory) + + vtkoutfile = outfilename+"_e1_fiber" + func_of_e1_vector.set_local(e1_fiber) + func_of_e1_vector.apply("insert") + vtk_py.convertQuadDataToVTK(mesh, V, func_of_e1, vtkoutfile, outdirectory) + + vtkoutfile = outfilename+"_e2_fiber" + func_of_e2_vector.set_local(e2_fiber) + func_of_e2_vector.apply("insert") + vtk_py.convertQuadDataToVTK(mesh, V, func_of_e2, vtkoutfile, outdirectory) + + if(MPI.rank(mpi_comm_world()) == 0): + print isrotatept + print outdirectory + outfilename + print "*******************************************************" + + if(isreturn): + + return func_of_e0, func_of_e1, func_of_e2 + + + diff --git a/vtk_py/addLVfiber_LDRB.pyc b/vtk_py/addLVfiber_LDRB.pyc new file mode 100644 index 0000000..6f3d0ae Binary files /dev/null and b/vtk_py/addLVfiber_LDRB.pyc differ diff --git a/vtk_py/addLocalCylindricalDirections.py b/vtk_py/addLocalCylindricalDirections.py new file mode 100644 index 0000000..f398997 --- /dev/null +++ b/vtk_py/addLocalCylindricalDirections.py @@ -0,0 +1,107 @@ +######################################################################## + +import math +import numpy +import vtk + +from createFloatArray import * +from getABPointsFromBoundsAndCenter import * +from getCellCenters import * + +######################################################################## + +def addLocalCylindricalDirections(ugrid_wall, + type_of_support="cell", + points_AB=None, + verbose=True): + + if (verbose): print '*** addLocalCylindricalDirections ***' + + if (points_AB == None): + points_AB = getABPointsFromBoundsAndCenter(ugrid_wall, verbose) + #print points_AB + assert (points_AB.GetNumberOfPoints() >= 2), "points_AB must have at least two points. Aborting." + point_A = numpy.array([0.]*3) + point_B = numpy.array([0.]*3) + points_AB.GetPoint( 0, point_A) + points_AB.GetPoint(points_AB.GetNumberOfPoints()-1, point_B) + #if (verbose): print "point_A =", point_A + #if (verbose): print "point_B =", point_B + eL = point_B - point_A + eL /= numpy.linalg.norm(eL) + #if (verbose): print "eL =", eL + + if (type_of_support == "cell"): + pdata_cell_centers = getCellCenters(ugrid_wall) + + if (type_of_support == "cell"): + nb_cells = ugrid_wall.GetNumberOfCells() + elif (type_of_support == "point"): + nb_cells = ugrid_wall.GetNumberOfPoints() + + farray_eR = createFloatArray("eRR", 3, nb_cells) + farray_eC = createFloatArray("eCC", 3, nb_cells) + farray_eL = createFloatArray("eLL", 3, nb_cells) + + farray_r = createFloatArray("r", 1, nb_cells) + farray_t = createFloatArray("t", 1, nb_cells) + farray_z = createFloatArray("z", 1, nb_cells) + + for num_cell in range(nb_cells): + #if (verbose): print "num_cell =", num_cell + + if (type_of_support == "cell"): + cell_center = numpy.array(pdata_cell_centers.GetPoints().GetPoint(num_cell)) + elif (type_of_support == "point"): + cell_center = numpy.array(ugrid_wall.GetPoints().GetPoint(num_cell)) + + #if (verbose): print "cell_center =", cell_center + + #eR = cell_center - point_A + #eR -= numpy.dot(eR,eL) * eL + #eR /= numpy.linalg.norm(eR) + + #eC = numpy.cross(eL, eR) + + eR = cell_center - point_A + eC = numpy.cross(eL, eR) + eC /= numpy.linalg.norm(eC) + eR = numpy.cross(eC, eL) + + if (numpy.dot(eR,eC) > 1e-6) or (numpy.dot(eR,eL) > 1e-6) or (numpy.dot(eC,eL) > 1e-6): print "WTF?!" + + farray_eR.InsertTuple(num_cell, eR) + farray_eC.InsertTuple(num_cell, eC) + farray_eL.InsertTuple(num_cell, eL) + + r = numpy.dot(cell_center - point_A, eR) + farray_r.InsertTuple(num_cell, [r]) + + t = math.atan2(eR[1], eR[0]) + t += (t<0.)*(2*math.pi) + farray_t.InsertTuple(num_cell, [t]) + + z = numpy.dot(cell_center - point_A, eL) + farray_z.InsertTuple(num_cell, [z]) + + if (type_of_support == "cell"): + ugrid_wall.GetCellData().AddArray(farray_eR) + ugrid_wall.GetCellData().AddArray(farray_eC) + ugrid_wall.GetCellData().AddArray(farray_eL) + ugrid_wall.GetCellData().AddArray(farray_r) + ugrid_wall.GetCellData().AddArray(farray_t) + ugrid_wall.GetCellData().AddArray(farray_z) + elif (type_of_support == "point"): + ugrid_wall.GetPointData().AddArray(farray_eR) + ugrid_wall.GetPointData().AddArray(farray_eC) + ugrid_wall.GetPointData().AddArray(farray_eL) + ugrid_wall.GetPointData().AddArray(farray_r) + ugrid_wall.GetPointData().AddArray(farray_t) + ugrid_wall.GetPointData().AddArray(farray_z) + + return ugrid_wall + +if (__name__ == "__main__"): + assert (len(sys.argv) in [2]), "Number of arguments must be 1. Aborting." + writeUGrid(addLocalCylindricalDirections(readUGrid(sys.argv[1])), sys.argv[1]) + diff --git a/vtk_py/addLocalCylindricalDirections.pyc b/vtk_py/addLocalCylindricalDirections.pyc new file mode 100644 index 0000000..f091847 Binary files /dev/null and b/vtk_py/addLocalCylindricalDirections.pyc differ diff --git a/vtk_py/addLocalFiberOrientation.py b/vtk_py/addLocalFiberOrientation.py new file mode 100644 index 0000000..2a7304d --- /dev/null +++ b/vtk_py/addLocalFiberOrientation.py @@ -0,0 +1,103 @@ +######################################################################## + +import sys +import math +import numpy +import vtk + +from addLocalFiberOrientation import * +from addLocalProlateSpheroidalDirections import * +from createFloatArray import * +from getABPointsFromBoundsAndCenter import * +from readSTL import * +from readUGrid import * +from writeUGrid import * + +######################################################################## + +def addLocalFiberOrientation(ugrid_wall, + fiber_angle_end, + fiber_angle_epi, + points_AB=None, + verbose=True): + + if (verbose): print '*** addLocalFiberOrientation ***' + + if (points_AB == None): + points_AB = getABPointsFromBoundsAndCenter(ugrid_wall, verbose) + assert (points_AB.GetNumberOfPoints() >= 2), "\"points_AB\" must have at least two points. Aborting." + point_A = numpy.array([0.]*3) + point_B = numpy.array([0.]*3) + points_AB.GetPoint( 0, point_A) + points_AB.GetPoint(points_AB.GetNumberOfPoints()-1, point_B) + eL = point_B - point_A + eL /= numpy.linalg.norm(eL) + + if (verbose): print "Computing local fiber orientation..." + + farray_norm_dist_end = ugrid_wall.GetCellData().GetArray("norm_dist_end") + farray_norm_dist_epi = ugrid_wall.GetCellData().GetArray("norm_dist_epi") + farray_eRR = ugrid_wall.GetCellData().GetArray("eRR") + farray_eCC = ugrid_wall.GetCellData().GetArray("eCC") + farray_eLL = ugrid_wall.GetCellData().GetArray("eLL") + + nb_cells = ugrid_wall.GetNumberOfCells() + + farray_fiber_angle = createFloatArray("fiber_angle", 1, nb_cells) + + farray_eF = createFloatArray("fiber vectors", 3, nb_cells) + farray_eS = createFloatArray("sheet vectors", 3, nb_cells) + farray_eN = createFloatArray("sheet normal vectors", 3, nb_cells) + + # LCL hack to have homogeneous fibers near apex + #bds = ugrid_wall.GetBounds() + #center = vtk.vtkCellCenters() + #center.SetInputData(ugrid_wall) + #center.Update() + ############################################### + + + for num_cell in range(nb_cells): + norm_dist_end = farray_norm_dist_end.GetTuple(num_cell)[0] + norm_dist_epi = farray_norm_dist_epi.GetTuple(num_cell)[0] + + fiber_angle_in_degrees = (1.-norm_dist_end) * fiber_angle_end + (1.-norm_dist_epi) * fiber_angle_epi + + # LCL hack to have homogeneous fibers near apex + #zloc = center.GetOutput().GetPoints().GetPoint(num_cell)[2] + #if(zloc < bds[4]+1): + # fiber_angle_in_degrees = 0 + ############################################### + + farray_fiber_angle.InsertTuple(num_cell, [fiber_angle_in_degrees]) + + eRR = numpy.array(farray_eRR.GetTuple(num_cell)) + eCC = numpy.array(farray_eCC.GetTuple(num_cell)) + eLL = numpy.array(farray_eLL.GetTuple(num_cell)) + + fiber_angle_in_radians = math.pi*fiber_angle_in_degrees/180 + eF = math.cos(fiber_angle_in_radians) * eCC + math.sin(fiber_angle_in_radians) * eLL + eS = eRR + eN = numpy.cross(eF, eS) + farray_eF.InsertTuple(num_cell, eF) + farray_eS.InsertTuple(num_cell, eS) + farray_eN.InsertTuple(num_cell, eN) + + if (verbose): print "Filling mesh..." + + ugrid_wall.GetCellData().AddArray(farray_fiber_angle) + ugrid_wall.GetCellData().AddArray(farray_eF) + ugrid_wall.GetCellData().AddArray(farray_eS) + ugrid_wall.GetCellData().AddArray(farray_eN) + +if (__name__ == "__main__"): + assert (len(sys.argv) in [4]), "Number of arguments must be 3. Aborting." + basename = sys.argv[1] + ugrid_wall = readUGrid(basename + "-Mesh.vtk") + pdata_end = readSTL(basename + "-End.stl") + pdata_epi = readSTL(basename + "-Epi.stl") + angle_end = float(sys.argv[2]) + angle_epi = float(sys.argv[3]) + addLocalProlateSpheroidalDirections(ugrid_wall, pdata_end, pdata_epi) + addLocalFiberOrientation(ugrid_wall, angle_end, angle_epi) + writeUGrid(ugrid_wall, basename + "-Mesh.vtk") diff --git a/vtk_py/addLocalFiberOrientation.pyc b/vtk_py/addLocalFiberOrientation.pyc new file mode 100644 index 0000000..7a7cd49 Binary files /dev/null and b/vtk_py/addLocalFiberOrientation.pyc differ diff --git a/vtk_py/addLocalFiberOrientation2.py b/vtk_py/addLocalFiberOrientation2.py new file mode 100644 index 0000000..40a1143 --- /dev/null +++ b/vtk_py/addLocalFiberOrientation2.py @@ -0,0 +1,142 @@ +######################################################################## + +import sys +import math +import random +import numpy +import vtk + +from createFloatArray import * +from getABPointsFromBoundsAndCenter import * + +######################################################################## + +def addLocalFiberOrientation2(ugrid_wall, + angles_end, + angles_epi, + points_AB=None, + sigma=0., + verbose=True): + + if (verbose): print '*** addLocalFiberOrientation2 ***' + + assert (len(angles_end) == len(angles_epi)), "angles_end and angle_epi must have same length (nb_long_nodes). Aborting." + nb_long_nodes = len(angles_end) + dz = 1./(nb_long_nodes-1) + nb_circ_nodes = len(angles_end[0]) + for angles in angles_end+angles_epi: + assert (len(angles) == nb_circ_nodes), "angles lists must have same length (nb_circ_nodes). Aborting." + dt = 2*math.pi/nb_circ_nodes + + if (points_AB == None): + points_AB = getABPointsFromBoundsAndCenter(ugrid_wall, verbose) + #print points_AB + assert (points_AB.GetNumberOfPoints() >= 2), "\"points_AB\" must have at least two points. Aborting." + point_A = numpy.array([0.]*3) + point_B = numpy.array([0.]*3) + points_AB.GetPoint( 0, point_A) + points_AB.GetPoint(points_AB.GetNumberOfPoints()-1, point_B) + #if (verbose): print "point_A =", point_A + #if (verbose): print "point_B =", point_B + + eL = point_B - point_A + eL /= numpy.linalg.norm(eL) + #if (verbose): print "eL =", eL + + if (verbose): print "Computing local fiber orientation..." + + farray_r = ugrid_wall.GetCellData().GetArray("r") + farray_t = ugrid_wall.GetCellData().GetArray("t") + farray_z = ugrid_wall.GetCellData().GetArray("z") + + farray_norm_dist_end = ugrid_wall.GetCellData().GetArray("norm_dist_end") + farray_norm_dist_epi = ugrid_wall.GetCellData().GetArray("norm_dist_epi") + + farray_norm_z_end = ugrid_wall.GetCellData().GetArray("norm_z_end") + farray_norm_z_epi = ugrid_wall.GetCellData().GetArray("norm_z_epi") + + farray_eRR = ugrid_wall.GetCellData().GetArray("eRR") + farray_eCC = ugrid_wall.GetCellData().GetArray("eCC") + farray_eLL = ugrid_wall.GetCellData().GetArray("eLL") + + nb_cells = ugrid_wall.GetNumberOfCells() + + farray_fiber_angle = createFloatArray("fiber_angle", 1, nb_cells) + + farray_eF = createFloatArray("eF", 3, nb_cells) + farray_eS = createFloatArray("eS", 3, nb_cells) + farray_eN = createFloatArray("eN", 3, nb_cells) + + for num_cell in range(nb_cells): + #print "num_cell = " + str(num_cell) + + t = farray_t.GetTuple(num_cell)[0] + i_t = int(t/dt/1.000001) + #print "i_t = " + str(i_t) + + zeta = (t - i_t*dt) / dt + #print "zeta = " + str(zeta) + + norm_z_end = farray_norm_z_end.GetTuple(num_cell)[0] + norm_z_epi = farray_norm_z_epi.GetTuple(num_cell)[0] + i_z_end = int(norm_z_end/dz/1.000001) + i_z_epi = int(norm_z_epi/dz/1.000001) + #print "i_z_end = " + str(i_z_end) + #print "i_z_epi = " + str(i_z_epi) + + eta_end = (norm_z_end - i_z_end*dz) / dz + eta_epi = (norm_z_epi - i_z_epi*dz) / dz + #print "eta_end = " + str(eta_end) + #print "eta_epi = " + str(eta_epi) + + t_ii_end = angles_end[i_z_end][i_t%nb_circ_nodes] + t_ji_end = angles_end[i_z_end][(i_t+1)%nb_circ_nodes] + t_ij_end = angles_end[(i_z_end+1)][i_t%nb_circ_nodes] + t_jj_end = angles_end[(i_z_end+1)][(i_t+1)%nb_circ_nodes] + t_ii_epi = angles_epi[i_z_epi][i_t%nb_circ_nodes] + t_ji_epi = angles_epi[i_z_epi][(i_t+1)%nb_circ_nodes] + t_ij_epi = angles_epi[(i_z_epi+1)][i_t%nb_circ_nodes] + t_jj_epi = angles_epi[(i_z_epi+1)][(i_t+1)%nb_circ_nodes] + #print "t_ii_end = " + str(t_ii_end) + #print "t_ji_end = " + str(t_ji_end) + #print "t_ij_end = " + str(t_ij_end) + #print "t_jj_end = " + str(t_jj_end) + #print "t_ii_epi = " + str(t_ii_epi) + #print "t_ji_epi = " + str(t_ji_epi) + #print "t_ij_epi = " + str(t_ij_epi) + #print "t_jj_epi = " + str(t_jj_epi) + + fiber_angle_end = t_ii_end * (1 - zeta - eta_end + zeta*eta_end) \ + + t_ji_end * (zeta - zeta*eta_end) \ + + t_ij_end * (eta_end - zeta*eta_end) \ + + t_jj_end * (zeta*eta_end) + fiber_angle_epi = t_ii_epi * (1 - zeta - eta_epi + zeta*eta_epi) \ + + t_ji_epi * (zeta - zeta*eta_epi) \ + + t_ij_epi * (eta_epi - zeta*eta_epi) \ + + t_jj_epi * (zeta*eta_epi) + + norm_dist_end = farray_norm_dist_end.GetTuple(num_cell)[0] + norm_dist_epi = farray_norm_dist_epi.GetTuple(num_cell)[0] + fiber_angle_in_degrees = (1.-norm_dist_end) * fiber_angle_end + (1.-norm_dist_epi) * fiber_angle_epi + if (sigma > 0.): fiber_angle_in_degrees *= random.normalvariate(1., sigma) + farray_fiber_angle.InsertTuple(num_cell, [fiber_angle_in_degrees]) + + eRR = numpy.array(farray_eRR.GetTuple(num_cell)) + eCC = numpy.array(farray_eCC.GetTuple(num_cell)) + eLL = numpy.array(farray_eLL.GetTuple(num_cell)) + + fiber_angle_in_radians = math.pi*fiber_angle_in_degrees/180 + eF = math.cos(fiber_angle_in_radians) * eCC + math.sin(fiber_angle_in_radians) * eLL + eS = eRR + eN = numpy.cross(eF, eS) + + farray_eF.InsertTuple(num_cell, eF) + farray_eS.InsertTuple(num_cell, eS) + farray_eN.InsertTuple(num_cell, eN) + + if (verbose): print "Filling mesh..." + + ugrid_wall.GetCellData().AddArray(farray_fiber_angle) + ugrid_wall.GetCellData().AddArray(farray_eF) + ugrid_wall.GetCellData().AddArray(farray_eS) + ugrid_wall.GetCellData().AddArray(farray_eN) diff --git a/vtk_py/addLocalFiberOrientation2.pyc b/vtk_py/addLocalFiberOrientation2.pyc new file mode 100644 index 0000000..cd8b2e0 Binary files /dev/null and b/vtk_py/addLocalFiberOrientation2.pyc differ diff --git a/vtk_py/addLocalFiberOrientation_infarct.py b/vtk_py/addLocalFiberOrientation_infarct.py new file mode 100644 index 0000000..1718f5b --- /dev/null +++ b/vtk_py/addLocalFiberOrientation_infarct.py @@ -0,0 +1,98 @@ +######################################################################## + +import sys +import math +import numpy +import vtk + +from addLocalFiberOrientation import * +from addLocalProlateSpheroidalDirections import * +from createFloatArray import * +from getABPointsFromBoundsAndCenter import * +from readSTL import * +from readUGrid import * +from writeUGrid import * + +######################################################################## + +def addLocalFiberOrientation_infarct(ugrid_wall, + fiber_angle_end, + fiber_angle_epi, + inf_fiber_angle_end, + inf_fiber_angle_epi, + matid, + points_AB=None, + verbose=True): + + if (verbose): print '*** addLocalFiberOrientation with infarct ***' + + if (points_AB == None): + points_AB = getABPointsFromBoundsAndCenter(ugrid_wall, verbose) + assert (points_AB.GetNumberOfPoints() >= 2), "\"points_AB\" must have at least two points. Aborting." + point_A = numpy.array([0.]*3) + point_B = numpy.array([0.]*3) + points_AB.GetPoint( 0, point_A) + points_AB.GetPoint(points_AB.GetNumberOfPoints()-1, point_B) + eL = point_B - point_A + eL /= numpy.linalg.norm(eL) + + if (verbose): print "Computing local fiber orientation..." + + farray_norm_dist_end = ugrid_wall.GetCellData().GetArray("norm_dist_end") + farray_norm_dist_epi = ugrid_wall.GetCellData().GetArray("norm_dist_epi") + farray_eRR = ugrid_wall.GetCellData().GetArray("eRR") + farray_eCC = ugrid_wall.GetCellData().GetArray("eCC") + farray_eLL = ugrid_wall.GetCellData().GetArray("eLL") + + nb_cells = ugrid_wall.GetNumberOfCells() + + farray_fiber_angle = createFloatArray("fiber_angle", 1, nb_cells) + + farray_eF = createFloatArray("fiber vectors", 3, nb_cells) + farray_eS = createFloatArray("sheet vectors", 3, nb_cells) + farray_eN = createFloatArray("sheet normal vectors", 3, nb_cells) + matid_data = createFloatArray("matid", 1, nb_cells) + + for num_cell in range(nb_cells): + norm_dist_end = farray_norm_dist_end.GetTuple(num_cell)[0] + norm_dist_epi = farray_norm_dist_epi.GetTuple(num_cell)[0] + + matid_data.InsertTuple(num_cell, [matid[num_cell]]) + if(matid[num_cell] == 1): + fiber_angle_in_degrees = (1.-norm_dist_end) * fiber_angle_end + (1.-norm_dist_epi) * fiber_angle_epi + else: + fiber_angle_in_degrees = (1.-norm_dist_end) * inf_fiber_angle_end + (1.-norm_dist_epi) * inf_fiber_angle_epi + + farray_fiber_angle.InsertTuple(num_cell, [fiber_angle_in_degrees]) + + eRR = numpy.array(farray_eRR.GetTuple(num_cell)) + eCC = numpy.array(farray_eCC.GetTuple(num_cell)) + eLL = numpy.array(farray_eLL.GetTuple(num_cell)) + + fiber_angle_in_radians = math.pi*fiber_angle_in_degrees/180 + eF = math.cos(fiber_angle_in_radians) * eCC + math.sin(fiber_angle_in_radians) * eLL + eS = eRR + eN = numpy.cross(eF, eS) + farray_eF.InsertTuple(num_cell, eF) + farray_eS.InsertTuple(num_cell, eS) + farray_eN.InsertTuple(num_cell, eN) + + if (verbose): print "Filling mesh..." + + ugrid_wall.GetCellData().AddArray(farray_fiber_angle) + ugrid_wall.GetCellData().AddArray(farray_eF) + ugrid_wall.GetCellData().AddArray(farray_eS) + ugrid_wall.GetCellData().AddArray(farray_eN) + ugrid_wall.GetCellData().AddArray(matid_data) + +if (__name__ == "__main__"): + assert (len(sys.argv) in [4]), "Number of arguments must be 3. Aborting." + basename = sys.argv[1] + ugrid_wall = readUGrid(basename + "-Mesh.vtk") + pdata_end = readSTL(basename + "-End.stl") + pdata_epi = readSTL(basename + "-Epi.stl") + angle_end = float(sys.argv[2]) + angle_epi = float(sys.argv[3]) + addLocalProlateSpheroidalDirections(ugrid_wall, pdata_end, pdata_epi) + addLocalFiberOrientation(ugrid_wall, angle_end, angle_epi) + writeUGrid(ugrid_wall, basename + "-Mesh.vtk") diff --git a/vtk_py/addLocalFiberOrientation_infarct.pyc b/vtk_py/addLocalFiberOrientation_infarct.pyc new file mode 100644 index 0000000..51b30e7 Binary files /dev/null and b/vtk_py/addLocalFiberOrientation_infarct.pyc differ diff --git a/vtk_py/addLocalProlateSpheroidalDirections.py b/vtk_py/addLocalProlateSpheroidalDirections.py new file mode 100644 index 0000000..4fe7121 --- /dev/null +++ b/vtk_py/addLocalProlateSpheroidalDirections.py @@ -0,0 +1,161 @@ +######################################################################## + +import sys +import math +import numpy +import vtk + +from createFloatArray import * +from getABPointsFromBoundsAndCenter import * +from getCellCenters import * +from getPDataNormals import * +from writePData import * + +######################################################################## + +def addLocalProlateSpheroidalDirections(ugrid_wall, + pdata_end, + pdata_epi, + type_of_support="cell", + epiflip=False, + endoflip=False, + apexflip=False, + points_AB=None, + eCCname="eCC", + eLLname="eLL", + eRRname="eRR", + verbose=True): + + if (verbose): print '*** addLocalProlateSpheroidalDirections ***' + + if (points_AB == None): + points_AB = getABPointsFromBoundsAndCenter(pdata_epi, verbose) + assert (points_AB.GetNumberOfPoints() == 2), "points_AB must have two points. Aborting." + point_A = numpy.array([0.]*3) + point_B = numpy.array([0.]*3) + points_AB.GetPoint(0, point_A) + points_AB.GetPoint(1, point_B) + if(apexflip): + eL = point_A - point_B + else: + eL = point_B - point_A + eL /= numpy.linalg.norm(eL) + + if (type_of_support == "cell"): + pdata_cell_centers = getCellCenters(ugrid_wall) + + if (verbose): print "Computing cell normals..." + + if(epiflip): + pdata_epi = getPDataNormals(pdata_epi, flip=1) + else: + pdata_epi = getPDataNormals(pdata_epi, flip=0) + + if(endoflip): + pdata_end = getPDataNormals(pdata_end, flip=1) + else: + pdata_end = getPDataNormals(pdata_end, flip=0) + + if (verbose): print "Computing surface bounds..." + + bounds_end = pdata_end.GetBounds() + bounds_epi = pdata_epi.GetBounds() + z_min_end = bounds_end[4] + z_min_epi = bounds_epi[4] + z_max_end = bounds_end[5] + z_max_epi = bounds_epi[5] + L_end = z_max_end-z_min_end + L_epi = z_max_epi-z_min_epi + + if (verbose): print "Initializing cell locators..." + + cell_locator_end = vtk.vtkCellLocator() + cell_locator_end.SetDataSet(pdata_end) + cell_locator_end.Update() + + cell_locator_epi = vtk.vtkCellLocator() + cell_locator_epi.SetDataSet(pdata_epi) + cell_locator_epi.Update() + + closest_point_end = [0.]*3 + closest_point_epi = [0.]*3 + generic_cell = vtk.vtkGenericCell() + cellId_end = vtk.mutable(0) + cellId_epi = vtk.mutable(0) + subId = vtk.mutable(0) + dist_end = vtk.mutable(0.) + dist_epi = vtk.mutable(0.) + + if (verbose): print "Computing local prolate spheroidal directions..." + + if (type_of_support == "cell"): + nb_cells = ugrid_wall.GetNumberOfCells() + elif (type_of_support == "point"): + nb_cells = ugrid_wall.GetNumberOfPoints() + + farray_norm_dist_end = createFloatArray("norm_dist_end", 1, nb_cells) + farray_norm_dist_epi = createFloatArray("norm_dist_epi", 1, nb_cells) + + farray_norm_z_end = createFloatArray("norm_z_end", 1, nb_cells) + farray_norm_z_epi = createFloatArray("norm_z_epi", 1, nb_cells) + + farray_eRR = createFloatArray(eRRname, 3, nb_cells) + farray_eCC = createFloatArray(eCCname, 3, nb_cells) + farray_eLL = createFloatArray(eLLname, 3, nb_cells) + + for num_cell in range(nb_cells): + if (type_of_support == "cell"): + cell_center = numpy.array(pdata_cell_centers.GetPoints().GetPoint(num_cell)) + elif (type_of_support == "point"): + cell_center = numpy.array(ugrid_wall.GetPoints().GetPoint(num_cell)) + cell_locator_end.FindClosestPoint(cell_center, closest_point_end, generic_cell, cellId_end, subId, dist_end) + cell_locator_epi.FindClosestPoint(cell_center, closest_point_epi, generic_cell, cellId_epi, subId, dist_epi) + + norm_dist_end = dist_end/(dist_end+dist_epi) + norm_dist_epi = dist_epi/(dist_end+dist_epi) + farray_norm_dist_end.InsertTuple(num_cell, [norm_dist_end]) + farray_norm_dist_epi.InsertTuple(num_cell, [norm_dist_epi]) + + norm_z_end = (closest_point_end[2]-z_min_end)/L_end + norm_z_epi = (closest_point_epi[2]-z_min_epi)/L_epi + farray_norm_z_end.InsertTuple(num_cell, [norm_z_end]) + farray_norm_z_epi.InsertTuple(num_cell, [norm_z_epi]) + + normal_end = numpy.reshape(pdata_end.GetCellData().GetNormals().GetTuple(cellId_end), (3)) + normal_epi = numpy.reshape(pdata_epi.GetCellData().GetNormals().GetTuple(cellId_epi), (3)) + eRR = -1*(1.-norm_dist_end) * normal_end + (1.-norm_dist_epi) * normal_epi + eRR /= numpy.linalg.norm(eRR) + eCC = numpy.cross(eL, eRR) + eCC /= numpy.linalg.norm(eCC) + eLL = numpy.cross(eRR, eCC) + farray_eRR.InsertTuple(num_cell, eRR) + farray_eCC.InsertTuple(num_cell, eCC) + farray_eLL.InsertTuple(num_cell, eLL) + + if (verbose): print "Filling mesh..." + + if (type_of_support == "cell"): + ugrid_wall.GetCellData().AddArray(farray_norm_dist_end) + ugrid_wall.GetCellData().AddArray(farray_norm_dist_epi) + ugrid_wall.GetCellData().AddArray(farray_norm_z_end) + ugrid_wall.GetCellData().AddArray(farray_norm_z_epi) + ugrid_wall.GetCellData().AddArray(farray_eRR) + ugrid_wall.GetCellData().AddArray(farray_eCC) + ugrid_wall.GetCellData().AddArray(farray_eLL) + elif (type_of_support == "point"): + ugrid_wall.GetPointData().AddArray(farray_norm_dist_end) + ugrid_wall.GetPointData().AddArray(farray_norm_dist_epi) + ugrid_wall.GetPointData().AddArray(farray_norm_z_end) + ugrid_wall.GetPointData().AddArray(farray_norm_z_epi) + ugrid_wall.GetPointData().AddArray(farray_eRR) + ugrid_wall.GetPointData().AddArray(farray_eCC) + ugrid_wall.GetPointData().AddArray(farray_eLL) + +if (__name__ == "__main__"): + assert (len(sys.argv) in [2]), "Number of arguments must be 1. Aborting." + basename = sys.argv[1] + ugrid_wall = readUGrid(basename + "-Mesh.vtk") + pdata_end = readSTL(basename + "-End.stl") + pdata_epi = readSTL(basename + "-Epi.stl") + addLocalProlateSpheroidalDirections(ugrid_wall, pdata_end, pdata_epi) + writeUGrid(ugrid_wall, basename + "-Mesh.vtk") diff --git a/vtk_py/addLocalProlateSpheroidalDirections.pyc b/vtk_py/addLocalProlateSpheroidalDirections.pyc new file mode 100644 index 0000000..476a4b9 Binary files /dev/null and b/vtk_py/addLocalProlateSpheroidalDirections.pyc differ diff --git a/vtk_py/addMappingFromPointsToCells.py b/vtk_py/addMappingFromPointsToCells.py new file mode 100644 index 0000000..c1c336f --- /dev/null +++ b/vtk_py/addMappingFromPointsToCells.py @@ -0,0 +1,43 @@ +######################################################################## + +import sys +import math +import numpy +import vtk + +from createIntArray import * + +######################################################################## + +def addMappingFromPointsToCells(ugrid_points, ugrid_cells, verbose=True): + + if (verbose): print '*** addMappingFromPointsToCells ***' + + nb_points = ugrid_points.GetNumberOfPoints() + nb_cells = ugrid_cells.GetNumberOfCells() + print "nb_points = " + str(nb_points) + print "nb_cells = " + str(nb_cells) + + cell_locator = vtk.vtkCellLocator() + cell_locator.SetDataSet(ugrid_cells) + cell_locator.Update() + + closest_point = [0.]*3 + generic_cell = vtk.vtkGenericCell() + num_cell = vtk.mutable(0) + subId = vtk.mutable(0) + dist = vtk.mutable(0.) + + iarray_num_cell = createIntArray("num_cell", 1, nb_points) + + for num_point in range(nb_points): + point = ugrid_points.GetPoint(num_point) + + cell_locator.FindClosestPoint(point, closest_point, generic_cell, num_cell, subId, dist) + #num_cell = cell_locator.FindCell(point) + + iarray_num_cell.InsertTuple(num_point, [num_cell]) + #print "num_point = " + str(num_point) + #print "num_cell = " + str(num_cell) + + ugrid_points.GetPointData().AddArray(iarray_num_cell) diff --git a/vtk_py/addMappingFromPointsToCells.pyc b/vtk_py/addMappingFromPointsToCells.pyc new file mode 100644 index 0000000..9c0c6be Binary files /dev/null and b/vtk_py/addMappingFromPointsToCells.pyc differ diff --git a/vtk_py/addSystolicStrains.py b/vtk_py/addSystolicStrains.py new file mode 100644 index 0000000..32d6b48 --- /dev/null +++ b/vtk_py/addSystolicStrains.py @@ -0,0 +1,50 @@ +######################################################################## + +import numpy +import vtk + +from mat_vec_tools import * +from createFloatArray import * + +######################################################################## + +def addSystolicStrains(mesh, verbose=True): + + if (verbose): print '*** addSystolicStrains ***' + + nb_cells = mesh.GetNumberOfCells() + + farray_F_dia = mesh.GetCellData().GetArray('F_dia') + farray_F_sys = mesh.GetCellData().GetArray('F_sys') + + farray_E_dia = createFloatArray('E_dia', 6, nb_cells) + farray_E_sys = createFloatArray('E_sys', 6, nb_cells) + farray_F_num = createFloatArray('F_num', 9, nb_cells) + farray_E_num = createFloatArray('E_num', 6, nb_cells) + + for num_cell in range(nb_cells): + F_dia = numpy.reshape(farray_F_dia.GetTuple(num_cell), (3,3), order='C') + F_sys = numpy.reshape(farray_F_sys.GetTuple(num_cell), (3,3), order='C') + #print 'F_dia =', F_dia + #print 'F_sys =', F_sys + + C = numpy.dot(numpy.transpose(F_dia), F_dia) + E = (C - numpy.eye(3))/2 + farray_E_dia.InsertTuple(num_cell, mat_sym_to_vec_col(E)) + + C = numpy.dot(numpy.transpose(F_sys), F_sys) + E = (C - numpy.eye(3))/2 + farray_E_sys.InsertTuple(num_cell, mat_sym_to_vec_col(E)) + + F = numpy.dot(F_sys, numpy.linalg.inv(F_dia)) + farray_F_num.InsertTuple(num_cell, numpy.reshape(F, 9, order='C')) + #print 'F =', F + + C = numpy.dot(numpy.transpose(F), F) + E = (C - numpy.eye(3))/2 + farray_E_num.InsertTuple(num_cell, mat_sym_to_vec_col(E)) + + mesh.GetCellData().AddArray(farray_E_dia) + mesh.GetCellData().AddArray(farray_E_sys) + mesh.GetCellData().AddArray(farray_F_num) + mesh.GetCellData().AddArray(farray_E_num) diff --git a/vtk_py/addSystolicStrains.pyc b/vtk_py/addSystolicStrains.pyc new file mode 100644 index 0000000..bd6442d Binary files /dev/null and b/vtk_py/addSystolicStrains.pyc differ diff --git a/vtk_py/clean_pdata.py b/vtk_py/clean_pdata.py new file mode 100644 index 0000000..34d34b6 --- /dev/null +++ b/vtk_py/clean_pdata.py @@ -0,0 +1,22 @@ +######################################################################## + +import sys +import vtk + +from mat_vec_tools import * + +######################################################################## + +def clean_pdata(pdata): + + cleanpdata = vtk.vtkCleanPolyData() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + cleanpdata.SetInputData(pdata) + else: + cleanpdata.SetInput(pdata) + cleanpdata.Update() + + return cleanpdata.GetOutput() + + + diff --git a/vtk_py/clean_pdata.pyc b/vtk_py/clean_pdata.pyc new file mode 100644 index 0000000..48e993d Binary files /dev/null and b/vtk_py/clean_pdata.pyc differ diff --git a/vtk_py/clipDomainForCutLVMesh.py b/vtk_py/clipDomainForCutLVMesh.py new file mode 100644 index 0000000..6502f9f --- /dev/null +++ b/vtk_py/clipDomainForCutLVMesh.py @@ -0,0 +1,32 @@ +######################################################################## + +import sys +import vtk + +from mat_vec_tools import * + +######################################################################## + +def clipDomainForCutLVMesh(domain, C, N, verbose=True): + + if (verbose): print '*** clipDomainForCutLVMesh ***' + + plane = vtk.vtkPlane() + plane.SetOrigin(C) + plane.SetNormal(N) + + clip = vtk.vtkClipPolyData() + clip.SetClipFunction(plane) + clip.GenerateClippedOutputOn() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + clip.SetInputData(domain) + else: + clip.SetInput(domain) + clip.Update() + clipped0 = clip.GetOutput(0) + clipped1 = clip.GetOutput(1) + + if (clipped0.GetNumberOfPoints() > clipped1.GetNumberOfPoints()): + return clipped0 + else: + return clipped1 diff --git a/vtk_py/clipDomainForCutLVMesh.pyc b/vtk_py/clipDomainForCutLVMesh.pyc new file mode 100644 index 0000000..a94d0b6 Binary files /dev/null and b/vtk_py/clipDomainForCutLVMesh.pyc differ diff --git a/vtk_py/clipSurfacesForCutLVMesh.py b/vtk_py/clipSurfacesForCutLVMesh.py new file mode 100644 index 0000000..e207c7c --- /dev/null +++ b/vtk_py/clipSurfacesForCutLVMesh.py @@ -0,0 +1,59 @@ +######################################################################## + +import sys +import vtk + +from mat_vec_tools import * +from readSTL import * +from writeSTL import * + +######################################################################## + +def clipSurfacesForCutLVMesh(endo, epi, height, direction=-1, verbose=True): + + if (verbose): print '*** clipSurfacesForCutLVMesh ***' + + plane = vtk.vtkPlane() + plane.SetNormal(0,0,direction) + plane.SetOrigin(0,0,height) + + clip = vtk.vtkClipPolyData() + clip.SetClipFunction(plane) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + clip.SetInputData(endo) + else: + clip.SetInput(endo) + clip.Update() + clipped_endo = clip.GetOutput(0) + + clip = vtk.vtkClipPolyData() + clip.SetClipFunction(plane) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + clip.SetInputData(epi) + else: + clip.SetInput(epi) + clip.Update() + clipped_epi = clip.GetOutput(0) + + return clipped_endo, clipped_epi + +if (__name__ == "__main__"): + assert (len(sys.argv) in [3,4]), 'Number of arguments must be 2 or 3.' + if (len(sys.argv) == 3): + endo_filename = sys.argv[1] + '-EndoLV.stl' + epi_filename = sys.argv[1] + '-EpiLV.stl' + clipped_endo_filename = sys.argv[1] + '_CutLV-Endo.stl' + clipped_epi_filename = sys.argv[1] + '_CutLV-Epi.stl' + height = float(sys.argv[2]) + elif (len(sys.argv) == 4): + endo_filename = sys.argv[1] + epi_filename = sys.argv[2] + clipped_endo_filename = 'clipped_endo.stl' + clipped_epi_filename = 'clipped_epi.stl' + height = float(sys.argv[3]) + endo = readSTL(endo_filename) + epi = readSTL(epi_filename) + clipped_endo, clipped_epi = clipSurfacesForCutLVMesh(endo, epi, height) + writeSTL(clipped_endo, clipped_endo_filename) + writeSTL(clipped_epi, clipped_epi_filename) + diff --git a/vtk_py/clipSurfacesForCutLVMesh.pyc b/vtk_py/clipSurfacesForCutLVMesh.pyc new file mode 100644 index 0000000..076e0d1 Binary files /dev/null and b/vtk_py/clipSurfacesForCutLVMesh.pyc differ diff --git a/vtk_py/clipSurfacesForCutLVMesh_PLY.py b/vtk_py/clipSurfacesForCutLVMesh_PLY.py new file mode 100644 index 0000000..c21bdfb --- /dev/null +++ b/vtk_py/clipSurfacesForCutLVMesh_PLY.py @@ -0,0 +1,59 @@ +######################################################################## + +import sys +import vtk + +from mat_vec_tools import * +from readPLY import * +from writeSTL import * + +######################################################################## + +def clipSurfacesForCutLVMesh_PLY(endo, epi, height, verbose=True): + + if (verbose): print '*** clipSurfacesForCutLVMesh ***' + + plane = vtk.vtkPlane() + plane.SetNormal(0,0,-1) + plane.SetOrigin(0,0,height) + + clip = vtk.vtkClipPolyData() + clip.SetClipFunction(plane) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + clip.SetInputData(endo) + else: + clip.SetInput(endo) + clip.Update() + clipped_endo = clip.GetOutput(0) + + clip = vtk.vtkClipPolyData() + clip.SetClipFunction(plane) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + clip.SetInputData(epi) + else: + clip.SetInput(epi) + clip.Update() + clipped_epi = clip.GetOutput(0) + + return clipped_endo, clipped_epi + +if (__name__ == "__main__"): + assert (len(sys.argv) in [3,4]), 'Number of arguments must be 2 or 3.' + if (len(sys.argv) == 3): + endo_filename = sys.argv[1] + epi_filename = sys.argv[1] + clipped_endo_filename = sys.argv[1] + '_CutLV-Endo.ply' + clipped_epi_filename = sys.argv[1] + '_CutLV-Epi.ply' + height = float(sys.argv[2]) + elif (len(sys.argv) == 4): + endo_filename = sys.argv[1] + epi_filename = sys.argv[2] + clipped_endo_filename = 'clipped_endo.stl' + clipped_epi_filename = 'clipped_epi.stl' + height = float(sys.argv[3]) + endo = readPLY(endo_filename) + epi = readPLY(epi_filename) + clipped_endo, clipped_epi = clipSurfacesForCutLVMesh(endo, epi, height) + writeSTL(clipped_endo, clipped_endo_filename) + writeSTL(clipped_epi, clipped_epi_filename) + diff --git a/vtk_py/clipSurfacesForCutLVMesh_PLY.pyc b/vtk_py/clipSurfacesForCutLVMesh_PLY.pyc new file mode 100644 index 0000000..a45e36b Binary files /dev/null and b/vtk_py/clipSurfacesForCutLVMesh_PLY.pyc differ diff --git a/vtk_py/clipSurfacesForFullLVMesh.py b/vtk_py/clipSurfacesForFullLVMesh.py new file mode 100644 index 0000000..aa6347a --- /dev/null +++ b/vtk_py/clipSurfacesForFullLVMesh.py @@ -0,0 +1,71 @@ +######################################################################## + +import sys +import vtk + +from mat_vec_tools import * +from readSTL import * +from writeSTL import * + +######################################################################## + +def clipSurfacesForFullLVMesh(endo, epi, verbose=True): + + if (verbose): print '*** clipSurfacesForFullLVMesh ***' + + endo_implicit_distance = vtk.vtkImplicitPolyDataDistance() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + endo_implicit_distance.SetInputData(endo) + else: + endo_implicit_distance.SetInput(endo) + + epi_implicit_distance = vtk.vtkImplicitPolyDataDistance() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + epi_implicit_distance.SetInputData(epi) + else: + epi_implicit_distance.SetInput(epi) + + epi_clip = vtk.vtkClipPolyData() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + epi_clip.SetInputData(epi) + else: + epi_clip.SetInput(epi) + epi_clip.SetClipFunction(endo_implicit_distance) + epi_clip.GenerateClippedOutputOn() + epi_clip.Update() + clipped_epi = epi_clip.GetOutput(0) + clipped_valve = epi_clip.GetOutput(1) + + endo_clip = vtk.vtkClipPolyData() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + endo_clip.SetInputData(endo) + else: + endo_clip.SetInput(endo) + endo_clip.SetClipFunction(epi_implicit_distance) + endo_clip.InsideOutOn() + endo_clip.Update() + clipped_endo = endo_clip.GetOutput(0) + + return clipped_endo, clipped_epi, clipped_valve + +if (__name__ == "__main__"): + assert (len(sys.argv) in [2,3]), 'Number of arguments must be 2 or 3.' + if (len(sys.argv) == 2): + endo_filename = sys.argv[1] + '-EndoLV.stl' + epi_filename = sys.argv[1] + '-EpiLV.stl' + clipped_endo_filename = sys.argv[1] + '_FullLV-Endo.stl' + clipped_epi_filename = sys.argv[1] + '_FullLV-Epi.stl' + clipped_valve_filename = sys.argv[1] + '_FullLV-Valve.stl' + elif (len(sys.argv) == 3): + endo_filename = sys.argv[1] + epi_filename = sys.argv[2] + clipped_endo_filename = 'clipped_endo.stl' + clipped_epi_filename = 'clipped_epi.stl' + clipped_valve_filename = 'clipped_valve.stl' + endo = readSTL(endo_filename) + epi = readSTL(epi_filename) + clipped_endo, clipped_epi, clipped_valve = clipSurfacesForFullLVMesh(endo, epi) + writeSTL(clipped_endo, clipped_endo_filename) + writeSTL(clipped_epi, clipped_epi_filename) + writeSTL(clipped_valve, clipped_valve_filename) + diff --git a/vtk_py/clipSurfacesForFullLVMesh.pyc b/vtk_py/clipSurfacesForFullLVMesh.pyc new file mode 100644 index 0000000..fe9207b Binary files /dev/null and b/vtk_py/clipSurfacesForFullLVMesh.pyc differ diff --git a/vtk_py/clipheart.py b/vtk_py/clipheart.py new file mode 100644 index 0000000..f2e4c34 --- /dev/null +++ b/vtk_py/clipheart.py @@ -0,0 +1,29 @@ +######################################################################## + +import sys +import vtk + +from mat_vec_tools import * + +######################################################################## + +def clipheart(domain, C, N, isinsideout, verbose=True): + + if (verbose): print '*** Slice Heart ***' + + plane = vtk.vtkPlane() + plane.SetOrigin(C) + plane.SetNormal(N) + + clipper = vtk.vtkClipPolyData() + clipper.SetClipFunction(plane) + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + clipper.SetInput(domain) + else: + clipper.SetInputData(domain) + clipper.SetInsideOut(isinsideout) + clipper.Update() + + return clipper.GetOutput(); + + diff --git a/vtk_py/clipheart.pyc b/vtk_py/clipheart.pyc new file mode 100644 index 0000000..dec4e80 Binary files /dev/null and b/vtk_py/clipheart.pyc differ diff --git a/vtk_py/clipheart_ugrid.py b/vtk_py/clipheart_ugrid.py new file mode 100644 index 0000000..c693e19 --- /dev/null +++ b/vtk_py/clipheart_ugrid.py @@ -0,0 +1,29 @@ +######################################################################## + +import sys +import vtk + +from mat_vec_tools import * + +######################################################################## + +def clipheart_ugrid(domain, C, N, isinsideout, verbose=True): + + if (verbose): print '*** Slice Heart ***' + + plane = vtk.vtkPlane() + plane.SetOrigin(C) + plane.SetNormal(N) + + clipper = vtk.vtkClipDataSet() + clipper.SetClipFunction(plane) + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + clipper.SetInput(domain) + else: + clipper.SetInputData(domain) + clipper.SetInsideOut(isinsideout) + clipper.Update() + + return clipper.GetOutput(); + + diff --git a/vtk_py/clipheart_ugrid.pyc b/vtk_py/clipheart_ugrid.pyc new file mode 100644 index 0000000..4698b88 Binary files /dev/null and b/vtk_py/clipheart_ugrid.pyc differ diff --git a/vtk_py/computeLVthickness.py b/vtk_py/computeLVthickness.py new file mode 100644 index 0000000..ea73911 --- /dev/null +++ b/vtk_py/computeLVthickness.py @@ -0,0 +1,226 @@ +####################################################################### + +import numpy +import vtk +import os +import sys +import math + +import vtk_py as myVTK + +######################################################################## +''' +def computeLVthickness(ugrid, field_type="point"): + + + assert (field_type in ["point", "cell"]), "\"field_type\" must be \"point\" or \"cell\". Aborting." + + pdata = myVTK.convertUGridtoPdata(ugrid) + C = myVTK.getcentroid(pdata) + ztop = pdata.GetBounds()[5] + C = [C[0], C[1], ztop-0.05] + clippedheart = myVTK.clipheart(pdata, C, [0,0,1], True) + epi , endo= myVTK.splitDomainBetweenEndoAndEpi(clippedheart) + + cleanepipdata = vtk.vtkCleanPolyData() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + cleanepipdata.SetInputData(epi) + else: + cleanepipdata.SetInput(epi) + cleanepipdata.Update() + cleanepi = cleanepipdata.GetOutput() + + cleanendopdata = vtk.vtkCleanPolyData() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + cleanendopdata.SetInputData(endo) + else: + cleanendopdata.SetInput(endo) + cleanendopdata.Update() + cleanendo = cleanendopdata.GetOutput() + + if(field_type == "point"): + + pointLocator = vtk.vtkPointLocator() + pointLocator.SetDataSet(cleanepi) + pointLocator.BuildLocator() + + thickness = vtk.vtkFloatArray() + thickness.SetName("Thickness") + thickness.SetNumberOfComponents(1) + + closest_epi_ptid = vtk.vtkIdList() + for ptid in range(0, cleanendo.GetNumberOfPoints()): + endopt = cleanendo.GetPoints().GetPoint(ptid) + closest_epi_ptid = pointLocator.FindClosestPoint(endopt) + closestepipt = cleanepi.GetPoints().GetPoint(closest_epi_ptid) + + distance = math.sqrt(vtk.vtkMath().Distance2BetweenPoints(endopt, closestepipt)) + thickness.InsertNextValue(distance) + + cleanendo.GetPointData().AddArray(thickness) + + if(field_type == "cell"): + pendo_cellcenter = vtk.vtkCellCenters() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + pendo_cellcenter.SetInputData(cleanendo) + else: + pendo_cellcenter.SetInput(cleanendo) + pendo_cellcenter.Update() + cleanendo_cellcenter = pendo_cellcenter.GetOutput() + + pepi_cellcenter = vtk.vtkCellCenters() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + pepi_cellcenter.SetInputData(cleanepi) + else: + pepi_cellcenter.SetInput(cleanepi) + pepi_cellcenter.Update() + cleanepi_cellcenter = pepi_cellcenter.GetOutput() + + pointLocator = vtk.vtkPointLocator() + pointLocator.SetDataSet(cleanepi_cellcenter) + pointLocator.BuildLocator() + + thickness = vtk.vtkFloatArray() + thickness.SetName("Thickness") + thickness.SetNumberOfComponents(1) + + closest_epi_ptid = vtk.vtkIdList() + for ptid in range(0, cleanendo.GetNumberOfCells()): + endopt = cleanendo_cellcenter.GetPoints().GetPoint(ptid) + closest_epi_ptid = pointLocator.FindClosestPoint(endopt) + closestepipt = cleanepi_cellcenter.GetPoints().GetPoint(closest_epi_ptid) + + distance = math.sqrt(vtk.vtkMath().Distance2BetweenPoints(endopt, closestepipt)) + thickness.InsertNextValue(distance) + + cleanendo.GetCellData().AddArray(thickness) + + #print "HERE" + + #myVTK.writePData(cleanendo, "/home/likchuan/Dropbox/UKentuckyData/endo.vtk") + + + + return cleanendo + +''' + +def computeLVthickness(ugrid, field_type="point"): + + + assert (field_type in ["point", "cell"]), "\"field_type\" must be \"point\" or \"cell\". Aborting." + + pdata = myVTK.convertUGridtoPdata(ugrid) + C = myVTK.getcentroid(pdata) + ztop = pdata.GetBounds()[5] + print ztop + C = [C[0], C[1], ztop-0.005] + #C = [C[0], C[1], ztop+0.05] + print C + + clippedheart = myVTK.clipheart(pdata, C, [0,0,1],isinsideout = 1) + + myVTK.writePData(clippedheart, "clippedheart.vtk") + + epi , endo= myVTK.splitDomainBetweenEndoAndEpi(clippedheart) + + myVTK.writePData(epi, "epi.vtk") + myVTK.writePData(endo, "endo.vtk") + + cleanepipdata = vtk.vtkCleanPolyData() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + cleanepipdata.SetInputData(epi) + else: + cleanepipdata.SetInput(epi) + cleanepipdata.Update() + cleanepi = cleanepipdata.GetOutput() + + cleanendopdata = vtk.vtkCleanPolyData() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + cleanendopdata.SetInputData(endo) + else: + cleanendopdata.SetInput(endo) + cleanendopdata.Update() + cleanendo = cleanendopdata.GetOutput() + + if(field_type == "point"): + + pointLocator = vtk.vtkPointLocator() + pointLocator.SetDataSet(cleanepi) + pointLocator.BuildLocator() + + thickness = vtk.vtkFloatArray() + thickness.SetName("Thickness") + thickness.SetNumberOfComponents(1) + + closest_epi_ptid = vtk.vtkIdList() + for ptid in range(0, cleanendo.GetNumberOfPoints()): + endopt = cleanendo.GetPoints().GetPoint(ptid) + closest_epi_ptid = pointLocator.FindClosestPoint(endopt) + closestepipt = cleanepi.GetPoints().GetPoint(closest_epi_ptid) + + distance = math.sqrt(vtk.vtkMath().Distance2BetweenPoints(endopt, closestepipt)) + thickness.InsertNextValue(distance) + + cleanendo.GetPointData().AddArray(thickness) + + if(field_type == "cell"): + pendo_cellcenter = vtk.vtkCellCenters() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + pendo_cellcenter.SetInputData(cleanendo) + else: + pendo_cellcenter.SetInput(cleanendo) + pendo_cellcenter.Update() + cleanendo_cellcenter = pendo_cellcenter.GetOutput() + + pepi_cellcenter = vtk.vtkCellCenters() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + pepi_cellcenter.SetInputData(cleanepi) + else: + pepi_cellcenter.SetInput(cleanepi) + pepi_cellcenter.Update() + cleanepi_cellcenter = pepi_cellcenter.GetOutput() + + pointLocator = vtk.vtkPointLocator() + pointLocator.SetDataSet(cleanepi_cellcenter) + pointLocator.BuildLocator() + + thickness = vtk.vtkFloatArray() + thickness.SetName("Thickness") + thickness.SetNumberOfComponents(1) + + closest_epi_ptid = vtk.vtkIdList() + for ptid in range(0, cleanendo.GetNumberOfCells()): + endopt = cleanendo_cellcenter.GetPoints().GetPoint(ptid) + closest_epi_ptid = pointLocator.FindClosestPoint(endopt) + closestepipt = cleanepi_cellcenter.GetPoints().GetPoint(closest_epi_ptid) + + distance = math.sqrt(vtk.vtkMath().Distance2BetweenPoints(endopt, closestepipt)) + thickness.InsertNextValue(distance) + + cleanendo.GetCellData().AddArray(thickness) + + #print "HERE" + + #myVTK.writePData(cleanendo, "cleanendo.vtk") + + + + return cleanendo + + + + + + + + + + + + + + + + + diff --git a/vtk_py/computeLVthickness.pyc b/vtk_py/computeLVthickness.pyc new file mode 100644 index 0000000..025c1e2 Binary files /dev/null and b/vtk_py/computeLVthickness.pyc differ diff --git a/vtk_py/computeRegionsForBiV.py b/vtk_py/computeRegionsForBiV.py new file mode 100644 index 0000000..4b9d504 --- /dev/null +++ b/vtk_py/computeRegionsForBiV.py @@ -0,0 +1,169 @@ +#coding=utf8 + +######################################################################## +### ### +### Created by Martin Genet, 2012-2015 ### +### ### +### University of California at San Francisco (UCSF), USA ### +### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### +### ### +######################################################################## + +import math +import numpy +import vtk +import os +import sys + +import vtk_py as myVTK + +######################################################################## + +def computeRegionsForBiV( + points, + pdata_endLV, + pdata_endRV, + pdata_epi, + verbose=0): + + #myVTK.myPrint(verbose, "*** computeRegionsForBiV ***") + #myVTK.myPrint(verbose, "Initializing cell locators...") + if (verbose): print "*** computeRegionsForBiV ***" + if (verbose): print "Initializing cell locators..." + + + (cell_locator_endLV, + closest_point_endLV, + generic_cell, + cellId_endLV, + subId, + dist_endLV) = myVTK.getCellLocator( + mesh=pdata_endLV, + verbose=verbose-1) + (cell_locator_endRV, + closest_point_endRV, + generic_cell, + cellId_endRV, + subId, + dist_endRV) = myVTK.getCellLocator( + mesh=pdata_endRV, + verbose=verbose-1) + (cell_locator_epi, + closest_point_epi, + generic_cell, + cellId_epi, + subId, + dist_epi) = myVTK.getCellLocator( + mesh=pdata_epi, + verbose=verbose-1) + + n_points = points.GetNumberOfPoints() + + iarray_region = myVTK.createIntArray("region_id", 1, n_points) + + for k_point in range(n_points): + point = numpy.array(points.GetPoint(k_point)) + cell_locator_endLV.FindClosestPoint( + point, + closest_point_endLV, + generic_cell, + cellId_endLV, + subId, + dist_endLV) + cell_locator_endRV.FindClosestPoint( + point, + closest_point_endRV, + generic_cell, + cellId_endRV, + subId, + dist_endRV) + cell_locator_epi.FindClosestPoint( + point, + closest_point_epi, + generic_cell, + cellId_epi, + subId, + dist_epi) + + if (dist_endRV == max(dist_endLV, dist_endRV, dist_epi)): + iarray_region.SetTuple(k_point, [0]) + elif (dist_epi == max(dist_endLV, dist_endRV, dist_epi)): + iarray_region.SetTuple(k_point, [1]) + elif (dist_endLV == max(dist_endLV, dist_endRV, dist_epi)): + iarray_region.SetTuple(k_point, [2]) + + return iarray_region + +######################################################################## + +def addRegionsToBiV( + ugrid_mesh, + pdata_endLV, + pdata_endRV, + pdata_epi, + verbose=0): + + #myVTK.myPrint(verbose, "*** addRegionsToBiV ***") + if (verbose): print "*** addRegionsToBiV ***" + + points = ugrid_mesh.GetPoints() + iarray_region = computeRegionsForBiV( + points=points, + pdata_endLV=pdata_endLV, + pdata_endRV=pdata_endRV, + pdata_epi=pdata_epi, + verbose=verbose-1) + ugrid_mesh.GetPointData().AddArray(iarray_region) + + cell_centers = myVTK.getCellCenters( + mesh=ugrid_mesh, + verbose=verbose-1) + iarray_region = computeRegionsForBiV( + points=cell_centers, + pdata_endLV=pdata_endLV, + pdata_endRV=pdata_endRV, + pdata_epi=pdata_epi, + verbose=verbose-1) + ugrid_mesh.GetCellData().AddArray(iarray_region) + +######################################################################## + +def addRegionsToBiV2D( + ugrid_mesh, + LVplane, + LVpoint, + RVplane, + RVpoint, + verbose=0): + + #myVTK.myPrint(verbose, "*** addRegionsToBiV2D ***") + if (verbose): print "*** addRegionsToBiV2D ***" + + tol = 1e-5 + + n_cells = ugrid_mesh.GetNumberOfCells() + + meshCellCenter = myVTK.getCellCenters(ugrid_mesh) + matid = myVTK.createIntArray("region_id", 1, n_cells) + + LVplanenorm = numpy.linalg.norm(LVplane) + LVPlane = 1.0/LVplanenorm*numpy.array(LVplane) + + RVplanenorm = numpy.linalg.norm(RVplane) + RVplane = 1.0/RVplanenorm*numpy.array(RVplane) + + + for ptid in range(n_cells): + x = meshCellCenter.GetPoints().GetPoint(ptid) + if((x[0] - LVpoint[0])*LVplane[0] + (x[1] - LVpoint[1])*LVplane[1] > tol): + matid.SetTuple(ptid,[0]) + elif((x[0] - RVpoint[0])*RVplane[0] + (x[1] - RVpoint[1])*RVplane[1] > tol): + matid.SetTuple(ptid,[1]) + else: + matid.SetTuple(ptid,[2]) + + ugrid_mesh.GetCellData().AddArray(matid) + + return ugrid_mesh + + diff --git a/vtk_py/computeRegionsForBiV.pyc b/vtk_py/computeRegionsForBiV.pyc new file mode 100644 index 0000000..559e3f6 Binary files /dev/null and b/vtk_py/computeRegionsForBiV.pyc differ diff --git a/vtk_py/computeVolume.py b/vtk_py/computeVolume.py new file mode 100644 index 0000000..93019ff --- /dev/null +++ b/vtk_py/computeVolume.py @@ -0,0 +1,66 @@ +######################################################################## + +import sys +import numpy +import vtk + +from mat_vec_tools import * +from createFloatArray import * +from vtk_py import * + +######################################################################## + + +def computeVolume(pdata, orientation): + + bd = pdata.GetBounds() + + # Define the cutting plane + plane=vtk.vtkPlane() + if(orientation == 'z'): + plane.SetOrigin(0,0,bd[5]-0.1) + plane.SetNormal(0,0,-1) + elif(orientation == 'x'): + plane.SetOrigin(bd[0]+0.1,0,0) + plane.SetNormal(1,0,0) + elif(orientation == 'n'): + plane.SetOrigin(0,0,bd[5]+100) + plane.SetNormal(0,0,-1) + + + # Need a plane collection for clipping + planeCollection = vtk.vtkPlaneCollection() + planeCollection.AddItem(plane) + + # The clipper generates a clipped polygonial model + clipper = vtk.vtkClipClosedSurface() + clipper.SetClippingPlanes(planeCollection) + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + clipper.SetInput(pdata) + else: + clipper.SetInputData(pdata) + clipper.SetGenerateFaces(1) + clipper.SetScalarModeToLabels() + clipper.Update() + + # Get volume using mass property + massprop = vtk.vtkMassProperties() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + massprop.SetInput(clipper.GetOutput()) + else: + massprop.SetInputData(clipper.GetOutput()) + return massprop.GetVolume() + +if (__name__ == "__main__"): + assert (len(sys.argv) in [2,3]), "Number of arguments must be 1 or 2. Aborting." + pdata_mesh = readSTL(sys.argv[1]) + if (len(sys.argv) == 2): + vol = computeVolume(pdata_mesh, "z") + elif (len(sys.argv) == 3): + vol = computeVolume(pdata_mesh, sys.argv[2]) + + print "Cavity volume = ", vol + + + + diff --git a/vtk_py/computeVolume.pyc b/vtk_py/computeVolume.pyc new file mode 100644 index 0000000..8478368 Binary files /dev/null and b/vtk_py/computeVolume.pyc differ diff --git a/vtk_py/convertAbaqusMeshToUGrid.py b/vtk_py/convertAbaqusMeshToUGrid.py new file mode 100644 index 0000000..3c61dda --- /dev/null +++ b/vtk_py/convertAbaqusMeshToUGrid.py @@ -0,0 +1,13 @@ +######################################################################## + +import sys + +from readAbaqusMesh import * +from writeUGrid import * + +######################################################################## + +name = sys.argv[1] + +mesh = readAbaqusMesh(name + ".inp", "hex") +writeUGrid(mesh, name + ".vtk") diff --git a/vtk_py/convertCellDataToXML.py b/vtk_py/convertCellDataToXML.py new file mode 100644 index 0000000..b4f47f8 --- /dev/null +++ b/vtk_py/convertCellDataToXML.py @@ -0,0 +1,26 @@ +######################################################################## + +import vtk + +######################################################################## + +def convertCellDataToXML(celldata, xmlfilename): + + xmlfile = open(xmlfilename, "w") + print >>xmlfile, "" + print >>xmlfile, "" + print >>xmlfile, "" + + cnt = 0 + for cellid in range(0,celldata.GetNumberOfTuples()): + data = celldata.GetTuple(cellid)[0] + print >>xmlfile, "" + cnt += 1 + + print >>xmlfile, "" + print >>xmlfile, "" + + + + + diff --git a/vtk_py/convertCellDataToXML.pyc b/vtk_py/convertCellDataToXML.pyc new file mode 100644 index 0000000..a968607 Binary files /dev/null and b/vtk_py/convertCellDataToXML.pyc differ diff --git a/vtk_py/convertPDataToXMLMesh.py b/vtk_py/convertPDataToXMLMesh.py new file mode 100644 index 0000000..6bf59aa --- /dev/null +++ b/vtk_py/convertPDataToXMLMesh.py @@ -0,0 +1,48 @@ +######################################################################## + +import vtk +import dolfin +import numpy as np +from vtk.util import numpy_support + +######################################################################## + +def convertPDataToXMLMesh(pdata): + + + num_pts = pdata.GetNumberOfPoints() + num_cells = pdata.GetNumberOfCells() + + #celltypes = numpy_support.vtk_to_numpy(pdata.GetCellTypesArray()) + #num_triangle = np.count_nonzero(celltypes == 5) + num_triangle = num_cells + + print "Number of points = ", num_pts + print "Number of triangle = ", num_triangle + + mesh = dolfin.Mesh() + editor = dolfin.MeshEditor() + editor.open(mesh, 2, 3) # top. and geom. dimension are both 2 + editor.init_vertices(num_pts) # number of vertices + editor.init_cells(num_triangle) # number of cells + + for p in range(0, num_pts): + pt = pdata.GetPoints().GetPoint(p) + editor.add_vertex(p, pt[0], pt[1], pt[2]) + + + cnt = 0 + for p in range(0, num_cells): + pts = vtk.vtkIdList() + pdata.GetCellPoints(p, pts) + if(pts.GetNumberOfIds() == 3): + editor.add_cell(cnt, pts.GetId(0), pts.GetId(1), pts.GetId(2)) + cnt = cnt + 1 + + editor.close() + + return mesh + + + + diff --git a/vtk_py/convertPDataToXMLMesh.pyc b/vtk_py/convertPDataToXMLMesh.pyc new file mode 100644 index 0000000..965edfd Binary files /dev/null and b/vtk_py/convertPDataToXMLMesh.pyc differ diff --git a/vtk_py/convertQuadDataToVTK.py b/vtk_py/convertQuadDataToVTK.py new file mode 100644 index 0000000..780ef41 --- /dev/null +++ b/vtk_py/convertQuadDataToVTK.py @@ -0,0 +1,106 @@ +import vtk as vtk +from dolfin import * +import vtk_py as vtk_py +import math as math +import numpy as np +import os as os + +def convertQuadDataToVTK(mesh, Fspace, data, filename=[], outdirectory=[]): + + nsubspace = Fspace.num_sub_spaces() + assert (nsubspace == 3), 'Only vectorspace works' + + dim = mesh.geometry().dim() + coord = Fspace.tabulate_dof_coordinates().reshape((-1, dim)) + npts = int(len(coord)/float(nsubspace)) + + my_first, my_last = Fspace.sub(0).dofmap().ownership_range() + + #dofmap = [Fspace.sub(i).dofmap().dofs() for i in range(0, nsubspace)] + x_dofs = np.arange(0, my_last-my_first, dim) + y_dofs = np.arange(1, my_last-my_first, dim) + z_dofs = np.arange(2, my_last-my_first, dim) + coord_dofs = np.arange(0, (my_last-my_first)/float(dim)) + + coord_reduce = coord[x_dofs] + + if(not isinstance(data, list)): + + points = vtk.vtkPoints() + vec = vtk.vtkFloatArray() + vec.SetNumberOfComponents(3) + vec.SetName("vector") + + for x_dof, y_dof, z_dof, coord_dof in zip(x_dofs, y_dofs, z_dofs, coord_dofs): + points.InsertNextPoint(coord_reduce[int(coord_dof)]) + #norm = math.sqrt(data.vector().array()[dofmap[0][p]]**2 + data.vector().array()[dofmap[1][p]]**2 + data.vector().array()[dofmap[2][p]]**2) + vec.InsertNextTuple3(data.vector().array()[x_dof], data.vector().array()[y_dof], data.vector().array()[z_dof]) + + + pdata = vtk.vtkPolyData() + pdata.SetPoints(points) + pdata.GetPointData().AddArray(vec) + + glyphfilter = vtk.vtkVertexGlyphFilter() + glyphfilter.AddInputData(pdata) + glyphfilter.Update() + + else: + + points = vtk.vtkPoints() + + vec_array = [] + for p in range(0, len(data)): + vec_array.append(vtk.vtkFloatArray()) + vec_array[p].SetNumberOfComponents(3) + vec_array[p].SetName("vector"+str(p)) + + for x_dof, y_dof, z_dof, coord_dof in zip(x_dofs, y_dofs, z_dofs, coord_dofs): + points.InsertNextPoint(coord_reduce[int(coord_dof)]) + #norm = math.sqrt(data.vector().array()[dofmap[0][p]]**2 + data.vector().array()[dofmap[1][p]]**2 + data.vector().array()[dofmap[2][p]]**2) + for p in range(0, len(data)): + vec_array[p].InsertNextTuple3(data[p].vector().array()[x_dof], \ + data[p].vector().array()[y_dof], \ + data[p].vector().array()[z_dof]) + + + pdata = vtk.vtkPolyData() + pdata.SetPoints(points) + for p in range(0, len(data)): + pdata.GetPointData().AddArray(vec_array[p]) + + glyphfilter = vtk.vtkVertexGlyphFilter() + glyphfilter.AddInputData(pdata) + glyphfilter.Update() + + + + if(not (not filename)): + filename_ = outdirectory + filename + str(MPI.rank(mpi_comm_world())) + '.vtp' + vtk_py.writeXMLPData(glyphfilter.GetOutput(), filename_, verbose=False) + + if(MPI.rank(mpi_comm_world()) == 0): + pvtufilename = outdirectory + filename + '.pvtp' + pvtufile = open(pvtufilename, 'w') + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + + for p in range(0, MPI.size(mpi_comm_world())): + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + pvtufile.close() + + + + + + + diff --git a/vtk_py/convertQuadDataToVTK.pyc b/vtk_py/convertQuadDataToVTK.pyc new file mode 100644 index 0000000..d23b835 Binary files /dev/null and b/vtk_py/convertQuadDataToVTK.pyc differ diff --git a/vtk_py/convertQuadScalarDataToVTK.py b/vtk_py/convertQuadScalarDataToVTK.py new file mode 100644 index 0000000..eb11a05 --- /dev/null +++ b/vtk_py/convertQuadScalarDataToVTK.py @@ -0,0 +1,101 @@ +import vtk as vtk +from dolfin import * +import vtk_py as vtk_py +import math as math +import numpy as np +import os as os + +def convertQuadScalarDataToVTK(mesh, Fspace, data, filename=[]): + + nsubspace = Fspace.num_sub_spaces() + assert (nsubspace == 0), 'Only scalar space works' + + dim = mesh.geometry().dim() + coord = Fspace.tabulate_dof_coordinates().reshape((-1, dim)) + npts = int(len(coord)) + + my_first, my_last = Fspace.dofmap().ownership_range() + + x_dofs = np.arange(0, my_last-my_first) + coord_dofs = np.arange(0, (my_last-my_first)) + + coord_reduce = coord[x_dofs] + + if(not isinstance(data, list)): + + points = vtk.vtkPoints() + scalar = vtk.vtkFloatArray() + scalar.SetNumberOfComponents(1) + scalar.SetName("scalar") + + for x_dof, coord_dof in zip(x_dofs, coord_dofs): + points.InsertNextPoint(coord_reduce[int(coord_dof)]) + scalar.InsertNextValue(data.vector().array()[x_dof]) + + + pdata = vtk.vtkPolyData() + pdata.SetPoints(points) + pdata.GetPointData().AddArray(scalar) + + glyphfilter = vtk.vtkVertexGlyphFilter() + glyphfilter.AddInputData(pdata) + glyphfilter.Update() + + else: + + points = vtk.vtkPoints() + + scalar_array = [] + for p in range(0, len(data)): + scalar_array.append(vtk.vtkFloatArray()) + scalar_array[p].SetNumberOfComponents(3) + scalar_array[p].SetName("scalar"+str(p)) + + for x_dof, coord_dof in zip(x_dofs, coord_dofs): + points.InsertNextPoint(coord_reduce[int(coord_dof)]) + for p in range(0, len(data)): + scalar_array[p].InsertNextValue(data[p].vector().array()[x_dof]) + + + pdata = vtk.vtkPolyData() + pdata.SetPoints(points) + for p in range(0, len(data)): + pdata.GetPointData().AddArray(scalar_array[p]) + + glyphfilter = vtk.vtkVertexGlyphFilter() + glyphfilter.AddInputData(pdata) + glyphfilter.Update() + + + + if(not (not filename)): + filename_ = filename + str(MPI.rank(mpi_comm_world())) + '.vtp' + #vtk_py.writeXMLPData(glyphfilter.GetOutput(), filename_, verbose=False) + vtk_py.writeXMLPData(pdata, filename_, verbose=False) + + if(MPI.rank(mpi_comm_world()) == 0): + pvtufilename = filename + '.pvtp' + pvtufile = open(pvtufilename, 'w') + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + + for p in range(0, MPI.size(mpi_comm_world())): + print >>pvtufile, "" + print >>pvtufile, "" + print >>pvtufile, "" + pvtufile.close() + + + + + return pdata + + + diff --git a/vtk_py/convertUGridToXMLMesh.py b/vtk_py/convertUGridToXMLMesh.py new file mode 100644 index 0000000..941c969 --- /dev/null +++ b/vtk_py/convertUGridToXMLMesh.py @@ -0,0 +1,81 @@ +######################################################################## + +import vtk +import dolfin +import numpy as np +from vtk.util import numpy_support + +######################################################################## + +def convertUGridToXMLMesh(ugrid): + + + num_pts = ugrid.GetNumberOfPoints() + num_cells = ugrid.GetNumberOfCells() + + celltypes = numpy_support.vtk_to_numpy(ugrid.GetCellTypesArray()) + + + num_tetra = np.count_nonzero(celltypes == 10) + + print "Number of points = ", num_pts + print "Number of tetra = ", num_tetra + + mesh = dolfin.Mesh() + editor = dolfin.MeshEditor() + editor.open(mesh, 3, 3) # top. and geom. dimension are both 2 + editor.init_vertices(num_pts) # number of vertices + editor.init_cells(num_tetra) # number of cells + + for p in range(0, num_pts): + pt = ugrid.GetPoints().GetPoint(p) + editor.add_vertex(p, pt[0], pt[1], pt[2]) + + + + cnt = 0 + for p in range(0, num_cells): + pts = vtk.vtkIdList() + ugrid.GetCellPoints(p, pts) + if(pts.GetNumberOfIds() == 4): + editor.add_cell(cnt, pts.GetId(0), pts.GetId(1), pts.GetId(2), pts.GetId(3)) + cnt = cnt + 1 + + editor.close() + + return mesh + +''' +def convertUGridToXMLMesh(ugrid): + + + num_pts = ugrid.GetNumberOfPoints() + num_cells = ugrid.GetNumberOfCells() + + print num_pts + print num_cells + + mesh = dolfin.Mesh() + editor = dolfin.MeshEditor() + editor.open(mesh, 3, 3) # top. and geom. dimension are both 2 + editor.init_vertices(num_pts) # number of vertices + editor.init_cells(num_cells) # number of cells + + for p in range(0, num_pts): + pt = ugrid.GetPoints().GetPoint(p) + editor.add_vertex(p, pt[0], pt[1], pt[2]) + + + + for p in range(0, num_cells): + pts = vtk.vtkIdList() + ugrid.GetCellPoints(p, pts) + editor.add_cell(p, pts.GetId(0), pts.GetId(1), pts.GetId(2), pts.GetId(3)) + + editor.close() + + return mesh + +''' + + diff --git a/vtk_py/convertUGridToXMLMesh.pyc b/vtk_py/convertUGridToXMLMesh.pyc new file mode 100644 index 0000000..a61a60f Binary files /dev/null and b/vtk_py/convertUGridToXMLMesh.pyc differ diff --git a/vtk_py/convertUGridtoPdata.py b/vtk_py/convertUGridtoPdata.py new file mode 100644 index 0000000..535ab09 --- /dev/null +++ b/vtk_py/convertUGridtoPdata.py @@ -0,0 +1,19 @@ +######################################################################## + +import vtk + +######################################################################## + + +def convertUGridtoPdata(ugrid): + + geometry = vtk.vtkGeometryFilter() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + geometry.SetInputData(ugrid) + else: + geometry.SetInput(ugrid) + + geometry.Update() + + return geometry.GetOutput() + diff --git a/vtk_py/convertUGridtoPdata.pyc b/vtk_py/convertUGridtoPdata.pyc new file mode 100644 index 0000000..25545d5 Binary files /dev/null and b/vtk_py/convertUGridtoPdata.pyc differ diff --git a/vtk_py/convertXMLMeshToUGrid.py b/vtk_py/convertXMLMeshToUGrid.py new file mode 100644 index 0000000..e06986b --- /dev/null +++ b/vtk_py/convertXMLMeshToUGrid.py @@ -0,0 +1,90 @@ +######################################################################## + +import vtk +import dolfin + +######################################################################## + +def convertXMLMeshToUGrid(mesh, p_region=None): + + connectivity = mesh.cells() + coords = mesh.coordinates() + + points = vtk.vtkPoints() + for coord in coords: + points.InsertNextPoint(coord[0], coord[1], coord[2]) + + + + '''part_id = vtk.vtkIntArray() + part_id.SetName("part_id") + if(p_region): + V = dolfin.FunctionSpace(mesh, "DG", 0) + dm = V.dofmap() + + for cell in dolfin.cells(mesh): + matid = p_region[cell] + part_id.InsertNextValue(matid)''' + + + + cellarray = vtk.vtkCellArray() + for cell in connectivity: + tetra = vtk.vtkTetra() + tetra.GetPointIds().SetId(0, cell[0]) + tetra.GetPointIds().SetId(1, cell[1]) + tetra.GetPointIds().SetId(2, cell[2]) + tetra.GetPointIds().SetId(3, cell[3]) + + cellarray.InsertNextCell(tetra) + + ugrid = vtk.vtkUnstructuredGrid() + ugrid.SetPoints(points) + ugrid.SetCells(tetra.GetCellType(), cellarray) + #ugrid.GetCellData().AddArray(part_id) + + return ugrid +''' + +def convertXMLMeshToUGrid(mesh, p_region=None): + + connectivity = mesh.cells() + coords = mesh.coordinates() + + points = vtk.vtkPoints() + for coord in coords: + points.InsertNextPoint(coord[0], coord[1], coord[2]) + + + part_id = vtk.vtkIntArray() + part_id.SetName("part_id") + if(p_region): + V = dolfin.FunctionSpace(mesh, "DG", 0) + dm = V.dofmap() + + for cell in dolfin.cells(mesh): + matid = p_region[cell] + part_id.InsertNextValue(matid) + + + + cellarray = vtk.vtkCellArray() + for cell in connectivity: + tetra = vtk.vtkTetra() + tetra.GetPointIds().SetId(0, cell[0]) + tetra.GetPointIds().SetId(1, cell[1]) + tetra.GetPointIds().SetId(2, cell[2]) + tetra.GetPointIds().SetId(3, cell[3]) + + cellarray.InsertNextCell(tetra) + + ugrid = vtk.vtkUnstructuredGrid() + ugrid.SetPoints(points) + ugrid.SetCells(tetra.GetCellType(), cellarray) + #ugrid.GetCellData().AddArray(part_id) + + return ugrid + +''' + + diff --git a/vtk_py/convertXMLMeshToUGrid.pyc b/vtk_py/convertXMLMeshToUGrid.pyc new file mode 100644 index 0000000..d01b76d Binary files /dev/null and b/vtk_py/convertXMLMeshToUGrid.pyc differ diff --git a/vtk_py/convertXMLMeshToUGrid2D.py b/vtk_py/convertXMLMeshToUGrid2D.py new file mode 100644 index 0000000..1b7c322 --- /dev/null +++ b/vtk_py/convertXMLMeshToUGrid2D.py @@ -0,0 +1,34 @@ +######################################################################## + +import vtk +import dolfin + +######################################################################## + +def convertXMLMeshToUGrid2D(mesh): + + connectivity = mesh.cells() + coords = mesh.coordinates() + + points = vtk.vtkPoints() + for coord in coords: + points.InsertNextPoint(coord[0], coord[1], coord[2]) + + cellarray = vtk.vtkCellArray() + for cell in connectivity: + triangle = vtk.vtkTriangle() + triangle.GetPointIds().SetId(0, cell[0]) + triangle.GetPointIds().SetId(1, cell[1]) + triangle.GetPointIds().SetId(2, cell[2]) + + cellarray.InsertNextCell(triangle) + + ugrid = vtk.vtkUnstructuredGrid() + ugrid.SetPoints(points) + ugrid.SetCells(triangle.GetCellType(), cellarray) + + return ugrid + + + + diff --git a/vtk_py/createFloatArray.py b/vtk_py/createFloatArray.py new file mode 100644 index 0000000..588691c --- /dev/null +++ b/vtk_py/createFloatArray.py @@ -0,0 +1,12 @@ +######################################################################## + +import vtk + +######################################################################## + +def createFloatArray(name, nb_components=1, nb_tuples=0, verbose=True): + farray = vtk.vtkFloatArray() + farray.SetName(name) + farray.SetNumberOfComponents(nb_components) + farray.SetNumberOfTuples(nb_tuples) + return farray \ No newline at end of file diff --git a/vtk_py/createFloatArray.pyc b/vtk_py/createFloatArray.pyc new file mode 100644 index 0000000..b7f0fce Binary files /dev/null and b/vtk_py/createFloatArray.pyc differ diff --git a/vtk_py/createIntArray.py b/vtk_py/createIntArray.py new file mode 100644 index 0000000..78488d6 --- /dev/null +++ b/vtk_py/createIntArray.py @@ -0,0 +1,12 @@ +######################################################################## + +import vtk + +######################################################################## + +def createIntArray(name, nb_components, nb_tuples, verbose=True): + iarray = vtk.vtkIntArray() + iarray.SetName(name) + iarray.SetNumberOfComponents(nb_components) + iarray.SetNumberOfTuples(nb_tuples) + return iarray diff --git a/vtk_py/createIntArray.pyc b/vtk_py/createIntArray.pyc new file mode 100644 index 0000000..18a554b Binary files /dev/null and b/vtk_py/createIntArray.pyc differ diff --git a/vtk_py/createLVmesh.py b/vtk_py/createLVmesh.py new file mode 100644 index 0000000..041180b --- /dev/null +++ b/vtk_py/createLVmesh.py @@ -0,0 +1,39 @@ +######################################################################## + +import sys +import vtk +import os +import inspect +import vtk_py + +######################################################################## + +def createLVmesh(casename, meshsize, epifilename, endofilename, verbose=True): + + if (verbose): print '*** createLVmesh ***' + + cur_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + + LVgeofile = cur_dir + "/LV.geo" + LVtempgeofile = "LVtemp.geo" + mshfilename = casename + ".msh" + vtkfilename = casename + ".vtk" + + cmd = "cp " + LVgeofile + " " + LVtempgeofile + os.system(cmd) + cmd = "sed -i.bak s/'<>'/'" + str(meshsize) + "'/g " + LVtempgeofile + os.system(cmd) + cmd = "sed -i.bak s/'<>'/'" + endofilename + "'/g " + LVtempgeofile + os.system(cmd) + cmd = "sed -i.bak s/'<>'/'" + epifilename + "'/g " + LVtempgeofile + os.system(cmd) + cmd = "gmsh -3 LVtemp.geo -o " + mshfilename + os.system(cmd) + cmd = "gmsh -3 LVtemp.geo -o " + vtkfilename + os.system(cmd) + cmd = "rm LVtemp.geo" + os.system(cmd) + + + + diff --git a/vtk_py/createLVmesh.pyc b/vtk_py/createLVmesh.pyc new file mode 100644 index 0000000..fab74de Binary files /dev/null and b/vtk_py/createLVmesh.pyc differ diff --git a/vtk_py/create_BiVmesh.py b/vtk_py/create_BiVmesh.py new file mode 100644 index 0000000..9ba70ca --- /dev/null +++ b/vtk_py/create_BiVmesh.py @@ -0,0 +1,50 @@ +######################################################################## +import vtk +import numpy as np +import vtk_py +import sys +import inspect +import os + +######################################################################## + +def create_BiVmesh(epicutfilename, LVendocutfilename, RVendocutfilename, casename="BiV", meshsize=0.5, gmshcmd="gmsh", iswritemesh=False, verbose=True): + + + if (verbose): print '*** create_BiVmesh ***' + + cur_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + + geofile = cur_dir + "/BiV.geo" + tempgeofile = "BiV_temp.geo" + print tempgeofile + print os.getcwd() + + meshfilename = casename+".vtk" + + cmd = "cp " + geofile + " " + tempgeofile + os.system(cmd) + + cmd = "sed -i.bak s/'<>'/'" + str(meshsize) + "'/g " + tempgeofile + os.system(cmd) + cmd = "sed -i.bak s/'<>'/'" + "\""+ str(LVendocutfilename).replace("/", "\/") + "\"" + "'/g " + tempgeofile + os.system(cmd) + cmd = "sed -i.bak s/'<>'/'" + "\""+ str(RVendocutfilename).replace("/", "\/") + "\"" + "'/g " + tempgeofile + os.system(cmd) + cmd = "sed -i.bak s/'<>'/'" + "\""+ str(epicutfilename).replace("/", "\/") + "\"" + "'/g " + tempgeofile + os.system(cmd) + cmd = gmshcmd+" -3 BiV_temp.geo -o " + meshfilename + os.system(cmd) + cmd = "rm BiV_temp.geo " + os.system(cmd) + + ugrid = vtk_py.readUGrid(meshfilename) + cmd = "rm meshfilename" + os.system(cmd) + + return ugrid + + + + + diff --git a/vtk_py/create_BiVmesh.pyc b/vtk_py/create_BiVmesh.pyc new file mode 100644 index 0000000..dec3055 Binary files /dev/null and b/vtk_py/create_BiVmesh.pyc differ diff --git a/vtk_py/create_ellipsoidal_LV.py b/vtk_py/create_ellipsoidal_LV.py new file mode 100644 index 0000000..c25abee --- /dev/null +++ b/vtk_py/create_ellipsoidal_LV.py @@ -0,0 +1,42 @@ +######################################################################## +import vtk +import numpy as np +import vtk_py +import sys +import inspect +import os + +######################################################################## + +def create_ellipsoidal_LV(casename="ellipsoidal", meshsize=0.3, gmshcmd="gmsh", iswritemesh=False, verbose=True): + + + if (verbose): print '*** create_ellipsoidal_LV ***' + + cur_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + + geofile = cur_dir + "/ellipsoidal.geo" + tempgeofile = "ellipsoidal_temp.geo" + print tempgeofile + print os.getcwd() + + meshfilename = casename+".vtk" + + cmd = "cp " + geofile + " " + tempgeofile + os.system(cmd) + + cmd = "sed -i.bak s/'<>'/'" + str(meshsize) + "'/g " + tempgeofile + os.system(cmd) + cmd = gmshcmd+" -3 ellipsoidal_temp.geo -o " + meshfilename + os.system(cmd) + cmd = "rm ellipsoidal_temp.geo" + os.system(cmd) + + ugrid = vtk_py.readUGrid(meshfilename) + + return ugrid + + + + + diff --git a/vtk_py/create_ellipsoidal_LV.pyc b/vtk_py/create_ellipsoidal_LV.pyc new file mode 100644 index 0000000..4b30afb Binary files /dev/null and b/vtk_py/create_ellipsoidal_LV.pyc differ diff --git a/vtk_py/ellipsoidal.geo b/vtk_py/ellipsoidal.geo new file mode 100644 index 0000000..5bc50ba --- /dev/null +++ b/vtk_py/ellipsoidal.geo @@ -0,0 +1,112 @@ +//Thick-Walled Prolate Spheroid Script + +scale = 11; +//lc = 0.05*scale; //this value changes the resolution of the mesh // medium +//lc = 0.025*scale; // Medium 2 mesh +//lc = 0.030*scale; // Medium mesh +lc = <>*scale; //Coarse +//lz_o = 1*scale; // outer long axis +//lx_o = 0.5*scale; // outer radius +wt=0.15*scale; + +lz_o=0.7*0.95*scale; +lx_o=0.35*0.95*scale; +wt=0.112*scale; + +lx_i=lx_o-wt; //inner radius +lz_i=lz_o-wt; //inner long axis + +Point(1) = {0,0,0,lc}; +Point(2) = {lx_o,0,0,lc}; +Point(3) = {0,0,-lz_o,lc}; +Point(4) = {lx_i,0,0,lc}; +Point(5) = {0,0,-lz_i,lc}; +Ellipse(1) = {2,1,3,3}; +Ellipse(2) = {4,1,5,5}; + +//OUTER ELLIPSOID + +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{1}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{3}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{6}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{9}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{12}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{15}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{18}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{21}; +} + +//INNER ELLIPSOID + +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{2}; +} + +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{27}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{30}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{33}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{36}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{39}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{42}; +} +Extrude {{0,0,1}, {0,0,0}, Pi/4} { + Line{45}; +} + +//Upper lines connecting inner and outer half spheroid and the related surfaces + + +Line(51) = {16, 9}; +Line(52) = {15, 8}; +Line(53) = {14, 7}; +Line(54) = {13, 6}; +Line(55) = {4, 2}; +Line(56) = {19, 12}; +Line(57) = {18, 11}; +Line(58) = {17, 10}; +Line Loop(59) = {40, 58, -16, -51}; +Plane Surface(60) = {59}; +Line Loop(61) = {51, -13, -52, 37}; +Plane Surface(62) = {61}; +Line Loop(63) = {52, -10, -53, 34}; +Plane Surface(64) = {63}; +Line Loop(65) = {53, -7, -54, 31}; +Plane Surface(66) = {65}; +Line Loop(67) = {54, -4, -55, 28}; +Plane Surface(68) = {67}; +Line Loop(69) = {55, -25, -56, 49}; +Plane Surface(70) = {69}; +Line Loop(71) = {56, -22, -57, 46}; +Plane Surface(72) = {71}; +Line Loop(73) = {57, -19, -58, 43}; +Plane Surface(74) = {73}; +Plane Surface(75) = {59}; +Surface Loop(76) = {14, 17, 20, 23, 26, 5, 8, 11, 64, 62, 38, 41, 44, 47, 50, 29, 32, 35, 66, 68, 70, 72, 74, 60}; +Volume(77) = {76}; +Physical Volume(1) = {77}; diff --git a/vtk_py/exportDynaDeformationGradients.py b/vtk_py/exportDynaDeformationGradients.py new file mode 100644 index 0000000..cd3a1b9 --- /dev/null +++ b/vtk_py/exportDynaDeformationGradients.py @@ -0,0 +1,36 @@ +######################################################################## + +import os + +######################################################################## +#open d3plot "''' + d3plot_file_basename + '''.d3plot" + +def exportDynaDeformationGradients(d3plot_file_basename, stateno): + lspp_file_name = d3plot_file_basename+'.lspp' + lspp_file = open(lspp_file_name, 'w') + lspp_file.write('''\ +open d3plot "d3plot" +selectpart shell off +fringe 91 +output "''' + d3plot_file_basename + '''.history#11"''' + str(stateno) + ''' 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1.000000 +fringe 92 +output "''' + d3plot_file_basename + '''.history#12"''' + str(stateno) + ''' 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1.000000 +fringe 93 +output "''' + d3plot_file_basename + '''.history#13"''' + str(stateno) + ''' 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1.000000 +fringe 94 +output "''' + d3plot_file_basename + '''.history#14"''' + str(stateno) + ''' 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1.000000 +fringe 95 +output "''' + d3plot_file_basename + '''.history#15"''' + str(stateno) + ''' 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1.000000 +fringe 96 +output "''' + d3plot_file_basename + '''.history#16"''' + str(stateno) + ''' 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1.000000 +fringe 97 +output "''' + d3plot_file_basename + '''.history#17"''' + str(stateno) + ''' 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1.000000 +fringe 98 +output "''' + d3plot_file_basename + '''.history#18"''' + str(stateno) + ''' 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1.000000 +fringe 99 +output "''' + d3plot_file_basename + '''.history#19"''' + str(stateno) + ''' 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1.000000 +exit +''') + lspp_file.close() +# os.system('Xvfb :2 -screen 0 1074x800x24 &') + os.system('/opt/lsprepost4.1_centos6/lspp41 -nographics c='+lspp_file_name) diff --git a/vtk_py/exportDynaDeformationGradients.pyc b/vtk_py/exportDynaDeformationGradients.pyc new file mode 100644 index 0000000..b3fbb73 Binary files /dev/null and b/vtk_py/exportDynaDeformationGradients.pyc differ diff --git a/vtk_py/extractCellFromPData.py b/vtk_py/extractCellFromPData.py new file mode 100644 index 0000000..898ee6f --- /dev/null +++ b/vtk_py/extractCellFromPData.py @@ -0,0 +1,29 @@ +import vtk +import vtk_py as vtk_py + +def extractCellFromPData(cellidlist, pdata): + + selectionNode = vtk.vtkSelectionNode() + selectionNode.SetFieldType(vtk.vtkSelectionNode.CELL); + selectionNode.SetContentType(vtk.vtkSelectionNode.INDICES); + selectionNode.SetSelectionList(cellidlist); + selection = vtk.vtkSelection(); + selection.AddNode(selectionNode); + extractSelection = vtk.vtkExtractSelection(); + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + extractSelection.SetInput(0, pdata); + extractSelection.SetInput(1, selection); + else: + extractSelection.SetInputData(0, pdata); + extractSelection.SetInputData(1, selection); + extractSelection.Update(); + extractbase = vtk.vtkGeometryFilter() + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + extractbase.SetInput(extractSelection.GetOutput()) + else: + extractbase.SetInputData(extractSelection.GetOutput()) + extractbase.Update() + + return extractbase.GetOutput() + + diff --git a/vtk_py/extractCellFromPData.pyc b/vtk_py/extractCellFromPData.pyc new file mode 100644 index 0000000..807d15e Binary files /dev/null and b/vtk_py/extractCellFromPData.pyc differ diff --git a/vtk_py/extractFeNiCsBiVFacet.py b/vtk_py/extractFeNiCsBiVFacet.py new file mode 100644 index 0000000..61eced8 --- /dev/null +++ b/vtk_py/extractFeNiCsBiVFacet.py @@ -0,0 +1,203 @@ +import vtk +import vtk_py as vtk_py +import dolfin as dolfin +import numpy as np + +def extractFeNiCsBiVFacet(ugrid, geometry="BiV"): + + tol = 1e-2 + + #ugrid = vtk_py.readUGrid(meshfilename) + + # Extract surface + geom = vtk.vtkGeometryFilter() + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + geom.SetInput(ugrid) + else: + geom.SetInputData(ugrid) + geom.Update() + surf = geom.GetOutput() + + bc_pts_locator = [] + bc_pts = [] + bc_pts_range = [] + bc_pts_map = [] + + # Extract Surface Normal + normal = vtk.vtkPolyDataNormals() + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + normal.SetInput(surf) + else: + normal.SetInputData(surf) + normal.ComputeCellNormalsOn() + normal.Update() + surf_w_norm = normal.GetOutput() + + #vtk_py.writePData(normal.GetOutput(), "normal.vtk") + + zmax = surf_w_norm.GetBounds()[5] + + surf_w_norm.BuildLinks() + idlist = vtk.vtkIdList() + basecellidlist = vtk.vtkIdTypeArray() + basesurf = vtk.vtkPolyData() + for p in range(0, surf_w_norm.GetNumberOfCells()): + zvec = surf_w_norm.GetCellData().GetNormals().GetTuple3(p)[2] + + surf_w_norm.GetCellPoints(p, idlist) + zpos = surf_w_norm.GetPoints().GetPoint(idlist.GetId(0))[2] + + if((abs(zvec - 1.0) < tol or abs(zvec + 1.0) < tol) and (abs(zmax - zpos) < tol)): + surf_w_norm.DeleteCell(p) + basecellidlist.InsertNextValue(p) + + basesurf = vtk_py.extractCellFromPData(basecellidlist, surf) + baseptlocator = vtk.vtkPointLocator() + baseptlocator.SetDataSet(basesurf) + baseptlocator.BuildLocator() + + ####################################################################### + + surf_w_norm.RemoveDeletedCells() + + + cleanpdata = vtk.vtkCleanPolyData() + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + cleanpdata.SetInput(surf_w_norm) + else: + cleanpdata.SetInputData(surf_w_norm) + cleanpdata.Update() + + connfilter = vtk.vtkPolyDataConnectivityFilter() + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + connfilter.SetInput(cleanpdata.GetOutput()) + else: + connfilter.SetInputData(cleanpdata.GetOutput()) + connfilter.Update() + + print "Total_num_points = ", cleanpdata.GetOutput().GetNumberOfPoints() + tpt = 0 + + if(geometry=="BiV"): + nsurf = 3 + else: + nsurf = 2 + + + for p in range(0,nsurf): + + pts = vtk.vtkPolyData() + + connfilter.SetExtractionModeToSpecifiedRegions() + [connfilter.DeleteSpecifiedRegion(k) for k in range(0,nsurf)] + connfilter.AddSpecifiedRegion(p) + connfilter.ScalarConnectivityOff() + connfilter.FullScalarConnectivityOff() + connfilter.Update() + + cleanpdata2 = vtk.vtkCleanPolyData() + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + cleanpdata2.SetInput(connfilter.GetOutput()) + else: + cleanpdata2.SetInputData(connfilter.GetOutput()) + cleanpdata2.Update() + + pts.DeepCopy(cleanpdata2.GetOutput()) + + tpt = tpt + cleanpdata2.GetOutput().GetNumberOfPoints() + + ptlocator = vtk.vtkPointLocator() + ptlocator.SetDataSet(pts) + ptlocator.BuildLocator() + + bc_pts_locator.append(ptlocator) + bc_pts.append(pts) + bc_pts_range.append([abs(pts.GetBounds()[k+1] - pts.GetBounds()[k]) for k in range(0, 6, 2)]) + + + #vtk_py.writePData(connfilter.GetOutput(), "/home/likchuan/Research/fenicsheartmesh/ellipsoidal/Geometry/test.vtk") + + print "Total_num_points = ", tpt + + Epiid = np.argmax(np.array([max(pts) for pts in bc_pts_range])) + maxzrank = np.array([pts[2] for pts in bc_pts_range]).argsort() + + + if(geometry=="BiV"): + LVid = maxzrank[1] + RVid = 3 - (LVid + Epiid) + bc_pts_map = [4, 4, 4, 4] + bc_pts_map[Epiid] = 1; bc_pts_map[LVid] = 2; bc_pts_map[RVid] = 3 + baseid = 3; + else: + LVid = maxzrank[0] + bc_pts_map = [4, 4, 4] + bc_pts_map[Epiid] = 1; bc_pts_map[LVid] = 2 + baseid = 2; + + + bc_pts_locator.append(baseptlocator) + bc_pts.append(basesurf) + + + dolfin_mesh = vtk_py.convertUGridToXMLMesh(ugrid) + dolfin_facets = dolfin.FacetFunction('size_t', dolfin_mesh) + dolfin_facets.set_all(0) + + for facet in dolfin.SubsetIterator(dolfin_facets, 0): + for locator in range(0,nsurf+1): + cnt = 0 + for p in range(0,3): + v0 = dolfin.Vertex(dolfin_mesh, facet.entities(0)[p]).x(0) + v1 = dolfin.Vertex(dolfin_mesh, facet.entities(0)[p]).x(1) + v2 = dolfin.Vertex(dolfin_mesh, facet.entities(0)[p]).x(2) + ptid = bc_pts_locator[locator].FindClosestPoint(v0, v1, v2) + x0 = bc_pts[locator].GetPoints().GetPoint(ptid) + dist = vtk.vtkMath.Distance2BetweenPoints([v0,v1,v2], x0) + if(dist < 1e-5): + cnt = cnt + 1 + + if(cnt == 3): + dolfin_facets[facet] = bc_pts_map[locator] + + + dolfin_edges = dolfin.EdgeFunction('size_t', dolfin_mesh) + dolfin_edges.set_all(0) + + epilocator = Epiid + lvendolocator = LVid + + for edge in dolfin.SubsetIterator(dolfin_edges, 0): + cnt_epi = 0; cnt_lvendo = 0; + for p in range(0,2): + v0 = dolfin.Vertex(dolfin_mesh, edge.entities(0)[p]).x(0) + v1 = dolfin.Vertex(dolfin_mesh, edge.entities(0)[p]).x(1) + v2 = dolfin.Vertex(dolfin_mesh, edge.entities(0)[p]).x(2) + + epiptid = bc_pts_locator[epilocator].FindClosestPoint(v0, v1, v2) + epix0 = bc_pts[epilocator].GetPoints().GetPoint(epiptid) + epidist = vtk.vtkMath.Distance2BetweenPoints([v0,v1,v2], epix0) + + topptid = bc_pts_locator[baseid].FindClosestPoint(v0, v1, v2) + topx0 = bc_pts[baseid].GetPoints().GetPoint(topptid) + topdist = vtk.vtkMath.Distance2BetweenPoints([v0,v1,v2], topx0) + + lvendoptid = bc_pts_locator[lvendolocator].FindClosestPoint(v0, v1, v2) + lvendox0 = bc_pts[lvendolocator].GetPoints().GetPoint(lvendoptid) + lvendodist = vtk.vtkMath.Distance2BetweenPoints([v0,v1,v2], lvendox0) + + if(topdist < 1e-5 and epidist < 1e-5): + cnt_epi = cnt_epi + 1 + + if(topdist < 1e-5 and lvendodist < 1e-5): + cnt_lvendo = cnt_lvendo + 1 + + if(cnt_epi == 2): + dolfin_edges[edge] = 1 + + if(cnt_lvendo == 2): + dolfin_edges[edge] = 2 + + + + return dolfin_mesh, dolfin_facets, dolfin_edges diff --git a/vtk_py/extractFeNiCsBiVFacet.pyc b/vtk_py/extractFeNiCsBiVFacet.pyc new file mode 100644 index 0000000..53e15b7 Binary files /dev/null and b/vtk_py/extractFeNiCsBiVFacet.pyc differ diff --git a/vtk_py/extractUGridBasedOnThreshold.py b/vtk_py/extractUGridBasedOnThreshold.py new file mode 100644 index 0000000..206d291 --- /dev/null +++ b/vtk_py/extractUGridBasedOnThreshold.py @@ -0,0 +1,37 @@ +import vtk as vtk +from vtk_py import * + +def extractUGridBasedOnThreshold(ugrid, arrayname, thresholdval): + + selectionNode = vtk.vtkSelectionNode(); + selectionNode.SetFieldType(vtk.vtkSelectionNode.CELL); + + idArray = vtk.vtkIdTypeArray() + if(type(thresholdval) == list): + selectionNode.SetContentType(vtk.vtkSelectionNode.THRESHOLDS); + idArray.SetNumberOfTuples(len(thresholdval)*2) + cnt = 0 + for tval in thresholdval: + idArray.SetValue(cnt, tval) + idArray.SetValue(cnt+1, tval) + cnt += 2 + else: + selectionNode.SetContentType(vtk.vtkSelectionNode.THRESHOLDS); + idArray.SetNumberOfTuples(2) + idArray.SetValue(0, thresholdval) + idArray.SetValue(1, thresholdval) + + selectionNode.SetSelectionList(idArray) + + selection = vtk.vtkSelection(); + selection.AddNode(selectionNode); + + extract = vtk.vtkExtractSelectedThresholds(); + extract.SetInputData(0, ugrid); + extract.SetInputData(1, selection); + extract.Update(); + + + return extract.GetOutput() + + diff --git a/vtk_py/extractUGridBasedOnThreshold.pyc b/vtk_py/extractUGridBasedOnThreshold.pyc new file mode 100644 index 0000000..28e130b Binary files /dev/null and b/vtk_py/extractUGridBasedOnThreshold.pyc differ diff --git a/vtk_py/extract_slice_thickness.py b/vtk_py/extract_slice_thickness.py new file mode 100644 index 0000000..0796db9 --- /dev/null +++ b/vtk_py/extract_slice_thickness.py @@ -0,0 +1,101 @@ +######################################################################## + +import sys +import vtk +import math + +from mat_vec_tools import * +from clean_pdata import * + +######################################################################## + +def extract_slice_thickness(nsubdivision, domain, LVctr, RVctr, Epictr, verbose=True): + + refinedmesh = vtk.vtkLoopSubdivisionFilter() + refinedmesh.SetNumberOfSubdivisions(nsubdivision); + refinedmesh.SetInput(domain) + refinedmesh.Update() + + featureEdges = vtk.vtkFeatureEdges(); + featureEdges.SetInput(refinedmesh.GetOutput()); + featureEdges.BoundaryEdgesOn(); + featureEdges.FeatureEdgesOff(); + featureEdges.ManifoldEdgesOff(); + featureEdges.NonManifoldEdgesOff(); + featureEdges.Update(); + + connectfilter = vtk.vtkPolyDataConnectivityFilter() + connectfilter.SetInput(featureEdges.GetOutput()) + connectfilter.SetExtractionModeToSpecifiedRegions() + connectfilter.Update() + + epi = vtk.vtkPolyData() + LVendo = vtk.vtkPolyData() + RVendo = vtk.vtkPolyData() + + #connectfilter.DeleteSpecifiedRegion(0) + #connectfilter.DeleteSpecifiedRegion(1) + #connectfilter.DeleteSpecifiedRegion(2) + #connectfilter.AddSpecifiedRegion(0) + connectfilter.SetExtractionModeToClosestPointRegion() + connectfilter.SetClosestPoint(Epictr[0], Epictr[1], Epictr[2]) + connectfilter.Update() + epi.DeepCopy(connectfilter.GetOutput()) + epi = clean_pdata(epi) + + #connectfilter.SetExtractionModeToSpecifiedRegions() + #connectfilter.DeleteSpecifiedRegion(0) + #connectfilter.AddSpecifiedRegion(1) + connectfilter.SetClosestPoint(RVctr[0], RVctr[1], RVctr[2]) + connectfilter.Update() + RVendo.DeepCopy(connectfilter.GetOutput()) + RVendo = clean_pdata(RVendo) + + #connectfilter.DeleteSpecifiedRegion(1) + #connectfilter.AddSpecifiedRegion(2) + connectfilter.SetClosestPoint(LVctr[0], LVctr[1], LVctr[2]) + connectfilter.Update() + LVendo.DeepCopy(connectfilter.GetOutput()) + LVendo = clean_pdata(LVendo) + + + epipointlocator = vtk.vtkPointLocator() + epipointlocator.SetDataSet(epi) + epipointlocator.BuildLocator() + + LVendopointlocator = vtk.vtkPointLocator() + LVendopointlocator.SetDataSet(LVendo) + LVendopointlocator.BuildLocator() + + RVendopointlocator = vtk.vtkPointLocator() + RVendopointlocator.SetDataSet(RVendo) + RVendopointlocator.BuildLocator() + + epidistance = vtk.vtkFloatArray() + epidistance.SetName("Thickness") + + + for p in range(0, epi.GetNumberOfPoints()): + pt = epi.GetPoints().GetPoint(p) + + RVendoid = RVendopointlocator.FindClosestPoint(pt) + RVendopt = RVendo.GetPoints().GetPoint(RVendoid) + + LVendoid = LVendopointlocator.FindClosestPoint(pt) + LVendopt = LVendo.GetPoints().GetPoint(LVendoid) + + disttoRVendo = math.sqrt(vtk.vtkMath.Distance2BetweenPoints(pt, RVendopt)) + disttoLVendo = math.sqrt(vtk.vtkMath.Distance2BetweenPoints(pt, LVendopt)) + + epidistance.InsertNextValue(min(disttoRVendo, disttoLVendo)) + + + epi.GetPointData().SetActiveScalars("Thickness") + epi.GetPointData().SetScalars(epidistance) + + return epi + + + + + diff --git a/vtk_py/extract_slice_thickness.pyc b/vtk_py/extract_slice_thickness.pyc new file mode 100644 index 0000000..c5e2870 Binary files /dev/null and b/vtk_py/extract_slice_thickness.pyc differ diff --git a/vtk_py/extract_slice_thickness_LVonly.py b/vtk_py/extract_slice_thickness_LVonly.py new file mode 100644 index 0000000..0628b98 --- /dev/null +++ b/vtk_py/extract_slice_thickness_LVonly.py @@ -0,0 +1,85 @@ +######################################################################## + +import sys +import vtk +import math + +from mat_vec_tools import * +from clean_pdata import * + +######################################################################## + +def extract_slice_thickness_LVonly(nsubdivision, domain, verbose=True): + + refinedmesh = vtk.vtkLoopSubdivisionFilter() + refinedmesh.SetNumberOfSubdivisions(nsubdivision); + refinedmesh.SetInput(domain) + refinedmesh.Update() + + bds = domain.GetBounds() + ctr = [0,0,0] + ctr[0] = 0.5*(bds[0] + bds[1]) + ctr[1] = 0.5*(bds[2] + bds[3]) + ctr[2] = 0.5*(bds[4] + bds[5]) + + featureEdges = vtk.vtkFeatureEdges(); + featureEdges.SetInput(refinedmesh.GetOutput()); + featureEdges.BoundaryEdgesOn(); + featureEdges.FeatureEdgesOff(); + featureEdges.ManifoldEdgesOff(); + featureEdges.NonManifoldEdgesOff(); + featureEdges.Update(); + + connectfilter = vtk.vtkPolyDataConnectivityFilter() + connectfilter.SetInput(featureEdges.GetOutput()) + connectfilter.SetExtractionModeToSpecifiedRegions() + connectfilter.Update() + + epi = vtk.vtkPolyData() + LVendo = vtk.vtkPolyData() + + connectfilter.SetExtractionModeToClosestPointRegion() + connectfilter.SetClosestPoint(ctr[0], ctr[1]+1000, ctr[2]+1000) + connectfilter.Update() + epi.DeepCopy(connectfilter.GetOutput()) + epi = clean_pdata(epi) + + + connectfilter.SetClosestPoint(ctr[0], ctr[1], ctr[2]) + connectfilter.Update() + LVendo.DeepCopy(connectfilter.GetOutput()) + LVendo = clean_pdata(LVendo) + + + epipointlocator = vtk.vtkPointLocator() + epipointlocator.SetDataSet(epi) + epipointlocator.BuildLocator() + + LVendopointlocator = vtk.vtkPointLocator() + LVendopointlocator.SetDataSet(LVendo) + LVendopointlocator.BuildLocator() + + epidistance = vtk.vtkFloatArray() + epidistance.SetName("Thickness") + + + for p in range(0, epi.GetNumberOfPoints()): + pt = epi.GetPoints().GetPoint(p) + + LVendoid = LVendopointlocator.FindClosestPoint(pt) + LVendopt = LVendo.GetPoints().GetPoint(LVendoid) + + disttoLVendo = math.sqrt(vtk.vtkMath.Distance2BetweenPoints(pt, LVendopt)) + + epidistance.InsertNextValue(disttoLVendo) + + + epi.GetPointData().SetActiveScalars("Thickness") + epi.GetPointData().SetScalars(epidistance) + + return epi + + + + + diff --git a/vtk_py/extract_slice_thickness_LVonly.pyc b/vtk_py/extract_slice_thickness_LVonly.pyc new file mode 100644 index 0000000..a10f576 Binary files /dev/null and b/vtk_py/extract_slice_thickness_LVonly.pyc differ diff --git a/vtk_py/findPointsInCell.py b/vtk_py/findPointsInCell.py new file mode 100644 index 0000000..2a9d0f0 --- /dev/null +++ b/vtk_py/findPointsInCell.py @@ -0,0 +1,40 @@ +######################################################################## + +import vtk + +######################################################################## + +def findPointsInCell(points, + cell, + verbose=True): + + ugrid_cell = vtk.vtkUnstructuredGrid() + ugrid_cell.SetPoints(cell.GetPoints()) + cell = vtk.vtkHexahedron() + for k_point in range(8): cell.GetPointIds().SetId(k_point, k_point) + cell_array_cell = vtk.vtkCellArray() + cell_array_cell.InsertNextCell(cell) + ugrid_cell.SetCells(vtk.VTK_HEXAHEDRON, cell_array_cell) + + geometry_filter = vtk.vtkGeometryFilter() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + geometry_filter.SetInputData(ugrid_cell) + else: + geometry_filter.SetInput(ugrid_cell) + geometry_filter.Update() + cell_boundary = geometry_filter.GetOutput() + + pdata_points = vtk.vtkPolyData() + pdata_points.SetPoints(points) + + enclosed_points_filter = vtk.vtkSelectEnclosedPoints() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + enclosed_points_filter.SetSurfaceData(cell_boundary) + enclosed_points_filter.SetInputData(pdata_points) + else: + enclosed_points_filter.SetSurface(cell_boundary) + enclosed_points_filter.SetInput(pdata_points) + enclosed_points_filter.Update() + + points_in_cell = [num_point for num_point in range(points.GetNumberOfPoints()) if enclosed_points_filter.GetOutput().GetPointData().GetArray('SelectedPoints').GetTuple(num_point)[0]] + return points_in_cell diff --git a/vtk_py/findPointsInCell.pyc b/vtk_py/findPointsInCell.pyc new file mode 100644 index 0000000..d7ce439 Binary files /dev/null and b/vtk_py/findPointsInCell.pyc differ diff --git a/vtk_py/getABPointsFromBoundsAndCenter.py b/vtk_py/getABPointsFromBoundsAndCenter.py new file mode 100644 index 0000000..d93aa69 --- /dev/null +++ b/vtk_py/getABPointsFromBoundsAndCenter.py @@ -0,0 +1,25 @@ +######################################################################## + +import vtk + +######################################################################## + +def getABPointsFromBoundsAndCenter(ugrid_wall, + verbose=True): + + if (verbose): print '*** getABPointsFromBoundsAndCenter ***' + + # Note that it is assumed here that the ventricle is vertical in the global coordinates system + bounds = ugrid_wall.GetBounds() + center = ugrid_wall.GetCenter() + #print "bounds =", bounds + #print "center =", center + point_A = [center[0], center[1], bounds[4]] + point_B = [center[0], center[1], bounds[5]] + #print "point_A =", point_A + #print "point_B =", point_B + points_AB = vtk.vtkPoints() + points_AB.InsertNextPoint(point_A) + points_AB.InsertNextPoint(point_B) + #print points_AB + return points_AB diff --git a/vtk_py/getABPointsFromBoundsAndCenter.pyc b/vtk_py/getABPointsFromBoundsAndCenter.pyc new file mode 100644 index 0000000..31f26e0 Binary files /dev/null and b/vtk_py/getABPointsFromBoundsAndCenter.pyc differ diff --git a/vtk_py/getABPointsFromTTTSectors.py b/vtk_py/getABPointsFromTTTSectors.py new file mode 100644 index 0000000..a4262fa --- /dev/null +++ b/vtk_py/getABPointsFromTTTSectors.py @@ -0,0 +1,69 @@ +#coding=utf8 + +######################################################################## + +import numpy +import vtk + +######################################################################## + +def getABPointsFromTTTSectors(ugrid_sectors, + verbose=True): + + if (verbose): print '*** getABPointsFromTTTSectors ***' + + nb_points = ugrid_sectors.GetNumberOfPoints() + nb_cells = ugrid_sectors.GetNumberOfCells() + + nb_csects = 12 + nb_rsects = 3 + nb_slices = nb_points / (nb_rsects+1) / (nb_csects+1) + if (verbose): print "nb_slices =", nb_slices + + zmin = ugrid_sectors.GetPoint(0)[2] + zmax = ugrid_sectors.GetPoint(ugrid_sectors.GetNumberOfPoints()-1)[2] + + dist_btw_slices = abs(zmin-zmax)/(nb_slices-1) + if (verbose): print "dist_btw_slices =", dist_btw_slices + + A = ugrid_sectors.GetPoints().GetPoint(0) + B = ugrid_sectors.GetPoints().GetPoint(6) + C = ugrid_sectors.GetPoints().GetPoint(3) + D = ugrid_sectors.GetPoints().GetPoint(9) + + #print A + #print B + #print C + #print D + + Px = ((A[0]*B[1]-A[1]*B[0])*(C[0]-D[0])-(A[0]-B[0])*(C[0]*D[1]-C[1]*D[0]))/((A[0]-B[0])*(C[1]-D[1])-(A[1]-B[1])*(C[0]-D[0])) + Py = ((A[0]*B[1]-A[1]*B[0])*(C[1]-D[1])-(A[1]-B[1])*(C[0]*D[1]-C[1]*D[0]))/((A[0]-B[0])*(C[1]-D[1])-(A[1]-B[1])*(C[0]-D[0])) + + #print Px + #print Py + + A = [Px, Py, zmin] + B = [Px, Py, zmax] + + if (verbose): print "A =", A + if (verbose): print "B =", B + + points_AB = vtk.vtkPoints() + points_AB.InsertNextPoint(A) + points_AB.InsertNextPoint(B) + + cells_AB = vtk.vtkCellArray() + cell_AB = vtk.vtkVertex() + cell_AB.GetPointIds().SetId(0, 0) + cells_AB.InsertNextCell(cell_AB) + cell_AB.GetPointIds().SetId(0, 1) + cells_AB.InsertNextCell(cell_AB) + + AB_ugrid = vtk.vtkUnstructuredGrid() + AB_ugrid.SetPoints(points_AB) + AB_ugrid.SetCells(vtk.VTK_VERTEX, cells_AB) + + return points_AB + + + diff --git a/vtk_py/getABPointsFromTTTSectors.pyc b/vtk_py/getABPointsFromTTTSectors.pyc new file mode 100644 index 0000000..d568710 Binary files /dev/null and b/vtk_py/getABPointsFromTTTSectors.pyc differ diff --git a/vtk_py/getCellCenters.py b/vtk_py/getCellCenters.py new file mode 100644 index 0000000..4088c23 --- /dev/null +++ b/vtk_py/getCellCenters.py @@ -0,0 +1,33 @@ +#coding=utf8 + +######################################################################## +### ### +### Created by Martin Genet, 2012-2015 ### +### ### +### University of California at San Francisco (UCSF), USA ### +### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### +### ### +######################################################################## + +import vtk + +import vtk_py as myVTK + +######################################################################## + +def getCellCenters( + mesh, + verbose=1): + + #myVTK.myPrint(verbose, "*** getCellCenters ***") + print "*** getCellCenters ***" + if (verbose): print "*** getCellCenters ***" + + filter_cell_centers = vtk.vtkCellCenters() + if(vtk.vtkVersion().GetVTKMajorVersion() > 5): + filter_cell_centers.SetInputData(mesh) + else: + filter_cell_centers.SetInput(mesh) + filter_cell_centers.Update() + + return filter_cell_centers.GetOutput() diff --git a/vtk_py/getCellCenters.pyc b/vtk_py/getCellCenters.pyc new file mode 100644 index 0000000..307b0c5 Binary files /dev/null and b/vtk_py/getCellCenters.pyc differ diff --git a/vtk_py/getCellLocator.py b/vtk_py/getCellLocator.py new file mode 100644 index 0000000..9c70895 --- /dev/null +++ b/vtk_py/getCellLocator.py @@ -0,0 +1,40 @@ +#coding=utf8 + +######################################################################## +### ### +### Created by Martin Genet, 2012-2015 ### +### ### +### University of California at San Francisco (UCSF), USA ### +### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### +### ### +######################################################################## + +import vtk + +import vtk_py as myVTK + +######################################################################## + +def getCellLocator( + mesh, + verbose=1): + + #myVTK.myPrint(verbose, "*** getCellLocator ***") + if (verbose): print "*** getCellLocator ***" + + cell_locator = vtk.vtkCellLocator() + cell_locator.SetDataSet(mesh) + cell_locator.Update() + + closest_point = [0.]*3 + generic_cell = vtk.vtkGenericCell() + k_cell = vtk.mutable(0) + subId = vtk.mutable(0) + dist = vtk.mutable(0.) + + return (cell_locator, + closest_point, + generic_cell, + k_cell, + subId, + dist) diff --git a/vtk_py/getCellLocator.pyc b/vtk_py/getCellLocator.pyc new file mode 100644 index 0000000..1b73c0c Binary files /dev/null and b/vtk_py/getCellLocator.pyc differ diff --git a/vtk_py/getPDataNormals.py b/vtk_py/getPDataNormals.py new file mode 100644 index 0000000..8ed76f7 --- /dev/null +++ b/vtk_py/getPDataNormals.py @@ -0,0 +1,24 @@ +######################################################################## + +import vtk + +######################################################################## + +def getPDataNormals(pdata, + flip=False, + verbose=True): + + if (verbose): print '*** getPDataNormals ***' + + poly_data_normals = vtk.vtkPolyDataNormals() + poly_data_normals.ComputePointNormalsOff() + poly_data_normals.ComputeCellNormalsOn() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + poly_data_normals.SetInputData(pdata) + else: + poly_data_normals.SetInput(pdata) + if (flip): poly_data_normals.FlipNormalsOn() + else: poly_data_normals.FlipNormalsOff() + poly_data_normals.Update() + + return poly_data_normals.GetOutput() diff --git a/vtk_py/getPDataNormals.pyc b/vtk_py/getPDataNormals.pyc new file mode 100644 index 0000000..548c724 Binary files /dev/null and b/vtk_py/getPDataNormals.pyc differ diff --git a/vtk_py/getcentroid.py b/vtk_py/getcentroid.py new file mode 100644 index 0000000..6ae2671 --- /dev/null +++ b/vtk_py/getcentroid.py @@ -0,0 +1,16 @@ +######################################################################## + +import sys +import vtk + +######################################################################## + +def getcentroid(domain, verbose=True): + + if (verbose): print '*** Get Centroid ***' + + bds = domain.GetBounds() + + return [0.5*(bds[0]+bds[1]), 0.5*(bds[2]+bds[3]), 0.5*(bds[4]+bds[5]) ] + + diff --git a/vtk_py/getcentroid.pyc b/vtk_py/getcentroid.pyc new file mode 100644 index 0000000..ede7f4f Binary files /dev/null and b/vtk_py/getcentroid.pyc differ diff --git a/vtk_py/lspost.cfile b/vtk_py/lspost.cfile new file mode 100644 index 0000000..5043403 --- /dev/null +++ b/vtk_py/lspost.cfile @@ -0,0 +1,3 @@ +$# LS-PrePost command file created by LS-PrePost 4.1 (Beta) - 22Sep2013(16:00) -64bit-Linux +$# Created on Jun-19-2014 (10:07:40) +openc d3plot "--nographics" diff --git a/vtk_py/mapCellDataToCellData.py b/vtk_py/mapCellDataToCellData.py new file mode 100644 index 0000000..910c134 --- /dev/null +++ b/vtk_py/mapCellDataToCellData.py @@ -0,0 +1,61 @@ +######################################################################## + +import numpy +import vtk + +from createFloatArray import * +from getCellCenters import * + +######################################################################## + +def mapCellDataToCellData(ugrid_data, + ugrid_mesh, + field_name, + cell_length_ratio_for_radius=0.5, + threshold_min=None, + threshold_max=None, + verbose=True): + + if (verbose): print '*** mapCellDataToCellData ***' + + pdata_data_cell_centers = getCellCenters(ugrid_data) + point_locator = vtk.vtkPointLocator() + point_locator.SetDataSet(pdata_data_cell_centers) + point_locator.Update() + + pdata_mesh_cell_centers = getCellCenters(ugrid_mesh) + + nb_components = ugrid_data.GetCellData().GetArray(field_name).GetNumberOfComponents() + nb_cells = ugrid_mesh.GetNumberOfCells() + farray_field_avg = createFloatArray(field_name+"_avg", + nb_components, + nb_cells) + farray_field_std = createFloatArray(field_name+"_std", + nb_components, + nb_cells) + + points_within_radius = vtk.vtkIdList() + + for num_cell in range(nb_cells): + l = (ugrid_mesh.GetCell(num_cell).GetLength2())**(0.5) + + point_locator.FindPointsWithinRadius(l*cell_length_ratio_for_radius, + pdata_mesh_cell_centers.GetPoint(num_cell), + points_within_radius) + + if (points_within_radius.GetNumberOfIds()): + values = [numpy.array(ugrid_data.GetCellData().GetArray(field_name).GetTuple(points_within_radius.GetId(num_id))) for num_id in range(points_within_radius.GetNumberOfIds())] + if (threshold_min != None): + values = [value for value in values if (numpy.linalg.norm(value) > threshold_min)] + if (threshold_max != None): + values = [value for value in values if (numpy.linalg.norm(value) < threshold_max)] + avg = numpy.mean(values, 0) + std = numpy.std(values, 0) + else: + avg = [0]*nb_components + std = [0]*nb_components + farray_field_avg.InsertTuple(num_cell, avg) + farray_field_std.InsertTuple(num_cell, std) + + ugrid_mesh.GetCellData().AddArray(farray_field_avg) + ugrid_mesh.GetCellData().AddArray(farray_field_std) diff --git a/vtk_py/mapCellDataToCellData.pyc b/vtk_py/mapCellDataToCellData.pyc new file mode 100644 index 0000000..43de873 Binary files /dev/null and b/vtk_py/mapCellDataToCellData.pyc differ diff --git a/vtk_py/mapPointDataToCellData.py b/vtk_py/mapPointDataToCellData.py new file mode 100644 index 0000000..606a637 --- /dev/null +++ b/vtk_py/mapPointDataToCellData.py @@ -0,0 +1,53 @@ +######################################################################## + +import numpy +import vtk + +from createFloatArray import * + +######################################################################## + +def mapPointDataToCellData(ugrid_data, + ugrid_mesh, + field_name, + cell_length_ratio_for_radius=0.5, + verbose=True): + + if (verbose): print '*** mapPointDataToCellData ***' + + nb_cells = ugrid_mesh.GetNumberOfCells() + + filter_cell_centers = vtk.vtkCellCenters() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + filter_cell_centers.SetInputData(ugrid_mesh) + else: + filter_cell_centers.SetInput(ugrid_mesh) + filter_cell_centers.Update() + pdata_mesh_cell_centers = filter_cell_centers.GetOutput() + + point_locator = vtk.vtkPointLocator() + point_locator.SetDataSet(ugrid_data) + point_locator.Update() + + nb_components = ugrid_data.GetPointData().GetArray(field_name).GetNumberOfComponents() + farray_tensors = createFloatArray(field_name, + nb_components, + nb_cells) + + points_within_radius = vtk.vtkIdList() + + for num_cell in range(nb_cells): + l = (ugrid_mesh.GetCell(num_cell).GetLength2())**(0.5) + + point_locator.FindPointsWithinRadius(l*cell_length_ratio_for_radius, + pdata_mesh_cell_centers.GetPoint(num_cell), + points_within_radius) + #points_in_cell = findPointsInCell(ugrid_data.GetPoints(), ugrid_mesh.GetCell(num_cell)) + + if (points_within_radius.GetNumberOfIds()): + tensor = sum([numpy.array(ugrid_data.GetPointData().GetArray(field_name).GetTuple(points_within_radius.GetId(num_id))) for num_id in range(points_within_radius.GetNumberOfIds())])/points_within_radius.GetNumberOfIds() + else: + tensor = [0]*nb_components + farray_tensors.InsertTuple(num_cell, tensor) + + ugrid_mesh.GetCellData().AddArray(farray_tensors) diff --git a/vtk_py/mapPointDataToCellData.pyc b/vtk_py/mapPointDataToCellData.pyc new file mode 100644 index 0000000..f8fe4ee Binary files /dev/null and b/vtk_py/mapPointDataToCellData.pyc differ diff --git a/vtk_py/mat_vec_tools.py b/vtk_py/mat_vec_tools.py new file mode 100644 index 0000000..816615a --- /dev/null +++ b/vtk_py/mat_vec_tools.py @@ -0,0 +1,31 @@ +######################################################################## + +import numpy + +######################################################################## + +def vec_col_to_mat_sym(vec): + if (numpy.size(vec,0) == 3): + return numpy.array([[vec[0], vec[2]], + [vec[2], vec[1]]]) + elif (numpy.size(vec,0) == 6): + return numpy.array([[vec[0], vec[3], vec[4]], + [vec[3], vec[1], vec[5]], + [vec[4], vec[5], vec[2]]]) +# return numpy.array([[vec[0], vec[3], vec[5]], +# [vec[3], vec[1], vec[4]], +# [vec[5], vec[4], vec[2]]]) + + else: + print 'Wrong vector dimension in vec_col_to_mat_sym. Aborting.' + exit() + +def mat_sym_to_vec_col(mat): + if (numpy.size(mat,0) == 2) and (numpy.size(mat,1) == 2): + return numpy.array([mat[0,0], mat[1,1], mat[0,1]]) + elif (numpy.size(mat,0) == 3) and (numpy.size(mat,1) == 3): + return numpy.array([mat[0,0], mat[1,1], mat[2,2], mat[0,1], mat[0,2], mat[1,2]]) + #return numpy.array([mat[0,0], mat[1,1], mat[2,2], mat[0,1], mat[1,2], mat[0,2]]) + else: + print 'Wrong matrix dimension in mat_sym_to_vec_col. Aborting.' + exit() diff --git a/vtk_py/mat_vec_tools.pyc b/vtk_py/mat_vec_tools.pyc new file mode 100644 index 0000000..eacd588 Binary files /dev/null and b/vtk_py/mat_vec_tools.pyc differ diff --git a/vtk_py/myPrint.py b/vtk_py/myPrint.py new file mode 100644 index 0000000..d05d59e --- /dev/null +++ b/vtk_py/myPrint.py @@ -0,0 +1,25 @@ +#coding=utf8 + +######################################################################## +### ### +### Created by Martin Genet, 2012-2015 ### +### ### +### University of California at San Francisco (UCSF), USA ### +### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### +### ### +######################################################################## + +import numpy + +import myVTKPythonLibrary as myVTK + +######################################################################## + +def myPrint( + verbose, + string): + + if not hasattr(myPrint, "initialized"): + myPrint.initialized = True + myPrint.verbose_ini = verbose + if (verbose > 0): print (myPrint.verbose_ini - verbose) * 4 * " " + string diff --git a/vtk_py/partitionmeshforEP.py b/vtk_py/partitionmeshforEP.py new file mode 100644 index 0000000..0ad12b5 --- /dev/null +++ b/vtk_py/partitionmeshforEP.py @@ -0,0 +1,66 @@ +# Partitioning Biventricular mesh for visualizing EP measurements +# This script partition the mesh into polar segments: +# Input: ugrid = vtk file containing BiVMesh +# : center = origin of the polar coordinate system (if none, mesh centroid will be used) +# : xaxis = direction corresponding to 0 degree in the polar coord system +# : nsectors = number of circular partition +# : nz = number of longitudinal partition +# : meas = measurements of size nz*nsectors + + +import vtk_py as vtk_py +import vtk +import numpy as np +import math as math + +def partitionmeshforEP(ugrid, nsector=6, nz=2, meas=None, center=None, xaxis=[1,0]): + + if(center == None): + midx = 0.5*(ugrid.GetBounds()[0] + ugrid.GetBounds()[1]) + midy = 0.5*(ugrid.GetBounds()[2] + ugrid.GetBounds()[3]) + center = [midx, midy] + + + cellcenter = vtk.vtkCellCenters() + cellcenter.SetInputData(ugrid) + cellcenter.Update() + + zpartition = np.linspace(ugrid.GetBounds()[4], ugrid.GetBounds()[5], nz+1) + apartition = np.linspace(-math.pi, math.pi, nsector+1) + + regid = vtk.vtkIntArray() + data = vtk.vtkFloatArray() + + for cellid in range(0, ugrid.GetNumberOfCells()): + x = cellcenter.GetOutput().GetPoints().GetPoint(cellid)[0] + y = cellcenter.GetOutput().GetPoints().GetPoint(cellid)[1] + z = cellcenter.GetOutput().GetPoints().GetPoint(cellid)[2] + + # Determine position in z direction + zloc = np.argmax(zpartition>z) + + # Determine position in theta direction + norm = np.linalg.norm([(x - midx), (y - midy)]) + angle = np.arctan2((y - midy)/norm, (x - midx)/norm) + sloc = np.argmax(apartition>angle) + + regloc = (zloc-1)*nsector + sloc + + regid.InsertNextValue(regloc) + data.InsertNextValue(meas[regloc-1]) + + regid.SetName("Regionid") + data.SetName("EP measurements") + + ugrid.GetCellData().AddArray(regid) + ugrid.GetCellData().AddArray(data) + + vtk_py.writeXMLUGrid(ugrid, "/home/lclee/Downloads/test.vtu") + + + + + + + + diff --git a/vtk_py/pyquaternion/__init__.py b/vtk_py/pyquaternion/__init__.py new file mode 100644 index 0000000..11d8282 --- /dev/null +++ b/vtk_py/pyquaternion/__init__.py @@ -0,0 +1,2 @@ +from quaternion import Quaternion +import quaternion diff --git a/vtk_py/pyquaternion/__init__.pyc b/vtk_py/pyquaternion/__init__.pyc new file mode 100644 index 0000000..11f3b4b Binary files /dev/null and b/vtk_py/pyquaternion/__init__.pyc differ diff --git a/vtk_py/pyquaternion/__pycache__/__init__.cpython-37.pyc b/vtk_py/pyquaternion/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..061774c Binary files /dev/null and b/vtk_py/pyquaternion/__pycache__/__init__.cpython-37.pyc differ diff --git a/vtk_py/pyquaternion/__pycache__/quaternion.cpython-37.pyc b/vtk_py/pyquaternion/__pycache__/quaternion.cpython-37.pyc new file mode 100644 index 0000000..e8116ea Binary files /dev/null and b/vtk_py/pyquaternion/__pycache__/quaternion.cpython-37.pyc differ diff --git a/vtk_py/pyquaternion/quaternion.py b/vtk_py/pyquaternion/quaternion.py new file mode 100644 index 0000000..6b5d4c1 --- /dev/null +++ b/vtk_py/pyquaternion/quaternion.py @@ -0,0 +1,1166 @@ +""" +This file is part of the pyquaternion python module + +Author: Kieran Wynn +Website: https://github.com/KieranWynn/pyquaternion +Documentation: http://kieranwynn.github.io/pyquaternion/ + +Version: 1.0.0 +License: The MIT License (MIT) + +Copyright (c) 2015 Kieran Wynn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +quaternion.py - This file defines the core Quaternion class + +""" + +from __future__ import absolute_import, division, print_function # Add compatibility for Python 2.7+ + +from math import sqrt, pi, sin, cos, asin, acos, atan2, exp, log +from copy import deepcopy +import numpy as np # Numpy is required for many vector operations + + +class Quaternion: + """Class to represent a 4-dimensional complex number or quaternion. + + Quaternion objects can be used generically as 4D numbers, + or as unit quaternions to represent rotations in 3D space. + + Attributes: + q: Quaternion 4-vector represented as a Numpy array + + """ + + def __init__(self, *args, **kwargs): + """Initialise a new Quaternion object. + + See Object Initialisation docs for complete behaviour: + + http://kieranwynn.github.io/pyquaternion/initialisation/ + + """ + s = len(args) + if s is 0: + # No positional arguments supplied + if len(kwargs) > 0: + # Keyword arguments provided + if ("scalar" in kwargs) or ("vector" in kwargs): + scalar = kwargs.get("scalar", 0.0) + if scalar is None: + scalar = 0.0 + else: + scalar = float(scalar) + + vector = kwargs.get("vector", []) + vector = self._validate_number_sequence(vector, 3) + + self.q = np.hstack((scalar, vector)) + elif ("real" in kwargs) or ("imaginary" in kwargs): + real = kwargs.get("real", 0.0) + if real is None: + real = 0.0 + else: + real = float(real) + + imaginary = kwargs.get("imaginary", []) + imaginary = self._validate_number_sequence(imaginary, 3) + + self.q = np.hstack((real, imaginary)) + elif ("axis" in kwargs) or ("radians" in kwargs) or ("degrees" in kwargs) or ("angle" in kwargs): + try: + axis = self._validate_number_sequence(kwargs["axis"], 3) + except KeyError: + raise ValueError( + "A valid rotation 'axis' parameter must be provided to describe a meaningful rotation." + ) + angle = kwargs.get('radians') or self.to_radians(kwargs.get('degrees')) or kwargs.get('angle') or 0.0 + self.q = Quaternion._from_axis_angle(axis, angle).q + elif "array" in kwargs: + self.q = self._validate_number_sequence(kwargs["array"], 4) + elif "matrix" in kwargs: + self.q = Quaternion._from_matrix(kwargs["matrix"]).q + else: + keys = sorted(kwargs.keys()) + elements = [kwargs[kw] for kw in keys] + if len(elements) is 1: + r = float(elements[0]) + self.q = np.array([r, 0.0, 0.0, 0.0]) + else: + self.q = self._validate_number_sequence(elements, 4) + + else: + # Default initialisation + self.q = np.array([1.0, 0.0, 0.0, 0.0]) + elif s is 1: + # Single positional argument supplied + if isinstance(args[0], Quaternion): + self.q = args[0].q + return + if args[0] is None: + raise TypeError("Object cannot be initialised from " + str(type(args[0]))) + try: + r = float(args[0]) + self.q = np.array([r, 0.0, 0.0, 0.0]) + return + except TypeError: + pass # If the single argument is not scalar, it should be a sequence + + self.q = self._validate_number_sequence(args[0], 4) + return + + else: + # More than one positional argument supplied + self.q = self._validate_number_sequence(args, 4) + + def __hash__(self): + return hash(tuple(self.q)) + + def _validate_number_sequence(self, seq, n): + """Validate a sequence to be of a certain length and ensure it's a numpy array of floats. + + Raises: + ValueError: Invalid length or non-numeric value + """ + if seq is None: + return np.zeros(n) + if len(seq) is n: + try: + l = [float(e) for e in seq] + except ValueError: + raise ValueError("One or more elements in sequence <" + repr(seq) + "> cannot be interpreted as a real number") + else: + return np.asarray(l) + elif len(seq) is 0: + return np.zeros(n) + else: + raise ValueError("Unexpected number of elements in sequence. Got: " + str(len(seq)) + ", Expected: " + str(n) + ".") + + # Initialise from matrix + @classmethod + def _from_matrix(cls, matrix): + """Initialise from matrix representation + + Create a Quaternion by specifying the 3x3 rotation or 4x4 transformation matrix + (as a numpy array) from which the quaternion's rotation should be created. + + """ + try: + shape = matrix.shape + except AttributeError: + raise TypeError("Invalid matrix type: Input must be a 3x3 or 4x4 numpy array or matrix") + + if shape == (3, 3): + R = matrix + elif shape == (4,4): + R = matrix[:-1][:,:-1] # Upper left 3x3 sub-matrix + else: + raise ValueError("Invalid matrix shape: Input must be a 3x3 or 4x4 numpy array or matrix") + + # Check matrix properties + if not np.allclose(np.dot(R, R.conj().transpose()), np.eye(3)): + raise ValueError("Matrix must be orthogonal, i.e. its transpose should be its inverse") + if not np.isclose(np.linalg.det(R), 1.0): + raise ValueError("Matrix must be special orthogonal i.e. its determinant must be +1.0") + + def decomposition_method(matrix): + """ Method supposedly able to deal with non-orthogonal matrices - NON-FUNCTIONAL! + Based on this method: http://arc.aiaa.org/doi/abs/10.2514/2.4654 + """ + x, y, z = 0, 1, 2 # indices + K = np.array([ + [R[x, x]-R[y, y]-R[z, z], R[y, x]+R[x, y], R[z, x]+R[x, z], R[y, z]-R[z, y]], + [R[y, x]+R[x, y], R[y, y]-R[x, x]-R[z, z], R[z, y]+R[y, z], R[z, x]-R[x, z]], + [R[z, x]+R[x, z], R[z, y]+R[y, z], R[z, z]-R[x, x]-R[y, y], R[x, y]-R[y, x]], + [R[y, z]-R[z, y], R[z, x]-R[x, z], R[x, y]-R[y, x], R[x, x]+R[y, y]+R[z, z]] + ]) + K = K / 3.0 + + e_vals, e_vecs = np.linalg.eig(K) + print('Eigenvalues:', e_vals) + print('Eigenvectors:', e_vecs) + max_index = np.argmax(e_vals) + principal_component = e_vecs[max_index] + return principal_component + + def trace_method(matrix): + """ + This code uses a modification of the algorithm described in: + https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf + which is itself based on the method described here: + http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ + + Altered to work with the column vector convention instead of row vectors + """ + m = matrix.conj().transpose() # This method assumes row-vector and postmultiplication of that vector + if m[2, 2] < 0: + if m[0, 0] > m[1, 1]: + t = 1 + m[0, 0] - m[1, 1] - m[2, 2] + q = [m[1, 2]-m[2, 1], t, m[0, 1]+m[1, 0], m[2, 0]+m[0, 2]] + else: + t = 1 - m[0, 0] + m[1, 1] - m[2, 2] + q = [m[2, 0]-m[0, 2], m[0, 1]+m[1, 0], t, m[1, 2]+m[2, 1]] + else: + if m[0, 0] < -m[1, 1]: + t = 1 - m[0, 0] - m[1, 1] + m[2, 2] + q = [m[0, 1]-m[1, 0], m[2, 0]+m[0, 2], m[1, 2]+m[2, 1], t] + else: + t = 1 + m[0, 0] + m[1, 1] + m[2, 2] + q = [t, m[1, 2]-m[2, 1], m[2, 0]-m[0, 2], m[0, 1]-m[1, 0]] + + q = np.array(q) + q *= 0.5 / sqrt(t); + return q + + return cls(array=trace_method(R)) + + # Initialise from axis-angle + @classmethod + def _from_axis_angle(cls, axis, angle): + """Initialise from axis and angle representation + + Create a Quaternion by specifying the 3-vector rotation axis and rotation + angle (in radians) from which the quaternion's rotation should be created. + + Params: + axis: a valid numpy 3-vector + angle: a real valued angle in radians + """ + mag_sq = np.dot(axis, axis) + if mag_sq == 0.0: + raise ZeroDivisionError("Provided rotation axis has no length") + # Ensure axis is in unit vector form + if (abs(1.0 - mag_sq) > 1e-12): + axis = axis / sqrt(mag_sq) + theta = angle / 2.0 + r = cos(theta) + i = axis * sin(theta) + + return cls(r, i[0], i[1], i[2]) + + @classmethod + def random(cls): + """Generate a random unit quaternion. + + Uniformly distributed across the rotation space + As per: http://planning.cs.uiuc.edu/node198.html + """ + r1, r2, r3 = np.random.random(3) + + q1 = sqrt(1.0 - r1) * (sin(2 * pi * r2)) + q2 = sqrt(1.0 - r1) * (cos(2 * pi * r2)) + q3 = sqrt(r1) * (sin(2 * pi * r3)) + q4 = sqrt(r1) * (cos(2 * pi * r3)) + + return cls(q1, q2, q3, q4) + + # Representation + def __str__(self): + """An informal, nicely printable string representation of the Quaternion object. + """ + return "{:.3f} {:+.3f}i {:+.3f}j {:+.3f}k".format(self.q[0], self.q[1], self.q[2], self.q[3]) + + def __repr__(self): + """The 'official' string representation of the Quaternion object. + + This is a string representation of a valid Python expression that could be used + to recreate an object with the same value (given an appropriate environment) + """ + return "Quaternion({}, {}, {}, {})".format(repr(self.q[0]), repr(self.q[1]), repr(self.q[2]), repr(self.q[3])) + + def __format__(self, formatstr): + """Inserts a customisable, nicely printable string representation of the Quaternion object + + The syntax for `format_spec` mirrors that of the built in format specifiers for floating point types. + Check out the official Python [format specification mini-language](https://docs.python.org/3.4/library/string.html#formatspec) for details. + """ + if formatstr.strip() == '': # Defualt behaviour mirrors self.__str__() + formatstr = '+.3f' + + string = \ + "{:" + formatstr +"} " + \ + "{:" + formatstr +"}i " + \ + "{:" + formatstr +"}j " + \ + "{:" + formatstr +"}k" + return string.format(self.q[0], self.q[1], self.q[2], self.q[3]) + + # Type Conversion + def __int__(self): + """Implements type conversion to int. + + Truncates the Quaternion object by only considering the real + component and rounding to the next integer value towards zero. + Note: to round to the closest integer, use int(round(float(q))) + """ + return int(self.q[0]) + + def __float__(self): + """Implements type conversion to float. + + Truncates the Quaternion object by only considering the real + component. + """ + return self.q[0] + + def __complex__(self): + """Implements type conversion to complex. + + Truncates the Quaternion object by only considering the real + component and the first imaginary component. + This is equivalent to a projection from the 4-dimensional hypersphere + to the 2-dimensional complex plane. + """ + return complex(self.q[0], self.q[1]) + + def __bool__(self): + return not (self == Quaternion(0.0)) + + def __nonzero__(self): + return not (self == Quaternion(0.0)) + + def __invert__(self): + return (self == Quaternion(0.0)) + + # Comparison + def __eq__(self, other): + """Returns true if the following is true for each element: + `absolute(a - b) <= (atol + rtol * absolute(b))` + """ + if isinstance(other, Quaternion): + r_tol = 1.0e-13 + a_tol = 1.0e-14 + try: + isEqual = np.allclose(self.q, other.q, rtol=r_tol, atol=a_tol) + except AttributeError: + raise AttributeError("Error in internal quaternion representation means it cannot be compared like a numpy array.") + return isEqual + return self.__eq__(self.__class__(other)) + + # Negation + def __neg__(self): + return self.__class__(array= -self.q) + + # Addition + def __add__(self, other): + if isinstance(other, Quaternion): + return self.__class__(array=self.q + other.q) + return self + self.__class__(other) + + def __iadd__(self, other): + return self + other + + def __radd__(self, other): + return self + other + + # Subtraction + def __sub__(self, other): + return self + (-other) + + def __isub__(self, other): + return self + (-other) + + def __rsub__(self, other): + return -(self - other) + + # Multiplication + def __mul__(self, other): + if isinstance(other, Quaternion): + return self.__class__(array=np.dot(self._q_matrix(), other.q)) + return self * self.__class__(other) + + def __imul__(self, other): + return self * other + + def __rmul__(self, other): + return self.__class__(other) * self + + # Division + def __div__(self, other): + if isinstance(other, Quaternion): + if other == self.__class__(0.0): + raise ZeroDivisionError("Quaternion divisor must be non-zero") + return self * other.inverse + return self.__div__(self.__class__(other)) + + def __idiv__(self, other): + return self.__div__(other) + + def __rdiv__(self, other): + return self.__class__(other) * self.inverse + + def __truediv__(self, other): + return self.__div__(other) + + def __itruediv__(self, other): + return self.__idiv__(other) + + def __rtruediv__(self, other): + return self.__rdiv__(other) + + # Exponentiation + def __pow__(self, exponent): + # source: https://en.wikipedia.org/wiki/Quaternion#Exponential.2C_logarithm.2C_and_power + exponent = float(exponent) # Explicitly reject non-real exponents + norm = self.norm + if norm > 0.0: + try: + n, theta = self.polar_decomposition + except ZeroDivisionError: + # quaternion is a real number (no vector or imaginary part) + return Quaternion(scalar=self.scalar ** exponent) + return (self.norm ** exponent) * Quaternion(scalar=cos(exponent * theta), vector=(n * sin(exponent * theta))) + return Quaternion(self) + + def __ipow__(self, other): + return self ** other + + def __rpow__(self, other): + return other ** float(self) + + # Quaternion Features + def _vector_conjugate(self): + return np.hstack((self.q[0], -self.q[1:4])) + + def _sum_of_squares(self): + return np.dot(self.q, self.q) + + @property + def conjugate(self): + """Quaternion conjugate, encapsulated in a new instance. + + For a unit quaternion, this is the same as the inverse. + + Returns: + A new Quaternion object clone with its vector part negated + """ + return self.__class__(scalar=self.scalar, vector= -self.vector) + + @property + def inverse(self): + """Inverse of the quaternion object, encapsulated in a new instance. + + For a unit quaternion, this is the inverse rotation, i.e. when combined with the original rotation, will result in the null rotation. + + Returns: + A new Quaternion object representing the inverse of this object + """ + ss = self._sum_of_squares() + if ss > 0: + return self.__class__(array=(self._vector_conjugate() / ss)) + else: + raise ZeroDivisionError("a zero quaternion (0 + 0i + 0j + 0k) cannot be inverted") + + @property + def norm(self): + """L2 norm of the quaternion 4-vector. + + This should be 1.0 for a unit quaternion (versor) + Slow but accurate. If speed is a concern, consider using _fast_normalise() instead + + Returns: + A scalar real number representing the square root of the sum of the squares of the elements of the quaternion. + """ + mag_squared = self._sum_of_squares() + return sqrt(mag_squared) + + @property + def magnitude(self): + return self.norm + + def _normalise(self): + """Object is guaranteed to be a unit quaternion after calling this + operation UNLESS the object is equivalent to Quaternion(0) + """ + if not self.is_unit(): + n = self.norm + if n > 0: + self.q = self.q / n + + def _fast_normalise(self): + """Normalise the object to a unit quaternion using a fast approximation method if appropriate. + + Object is guaranteed to be a quaternion of approximately unit length + after calling this operation UNLESS the object is equivalent to Quaternion(0) + """ + if not self.is_unit(): + mag_squared = np.dot(self.q, self.q) + if (mag_squared == 0): + return + if (abs(1.0 - mag_squared) < 2.107342e-08): + mag = ((1.0 + mag_squared) / 2.0) # More efficient. Pade approximation valid if error is small + else: + mag = sqrt(mag_squared) # Error is too big, take the performance hit to calculate the square root properly + + self.q = self.q / mag + + @property + def normalised(self): + """Get a unit quaternion (versor) copy of this Quaternion object. + + A unit quaternion has a `norm` of 1.0 + + Returns: + A new Quaternion object clone that is guaranteed to be a unit quaternion + """ + q = Quaternion(self) + q._normalise() + return q + + @property + def polar_unit_vector(self): + vector_length = np.linalg.norm(self.vector) + if vector_length <= 0.0: + raise ZeroDivisionError('Quaternion is pure real and does not have a unique unit vector') + return self.vector / vector_length + + @property + def polar_angle(self): + return acos(self.scalar / self.norm) + + @property + def polar_decomposition(self): + """ + Returns the unit vector and angle of a non-scalar quaternion according to the following decomposition + + q = q.norm() * (e ** (q.polar_unit_vector * q.polar_angle)) + + source: https://en.wikipedia.org/wiki/Polar_decomposition#Quaternion_polar_decomposition + """ + return self.polar_unit_vector, self.polar_angle + + @property + def unit(self): + return self.normalised + + def is_unit(self, tolerance=1e-14): + """Determine whether the quaternion is of unit length to within a specified tolerance value. + + Params: + tolerance: [optional] maximum absolute value by which the norm can differ from 1.0 for the object to be considered a unit quaternion. Defaults to `1e-14`. + + Returns: + `True` if the Quaternion object is of unit length to within the specified tolerance value. `False` otherwise. + """ + return abs(1.0 - self._sum_of_squares()) < tolerance # if _sum_of_squares is 1, norm is 1. This saves a call to sqrt() + + def _q_matrix(self): + """Matrix representation of quaternion for multiplication purposes. + """ + return np.array([ + [self.q[0], -self.q[1], -self.q[2], -self.q[3]], + [self.q[1], self.q[0], -self.q[3], self.q[2]], + [self.q[2], self.q[3], self.q[0], -self.q[1]], + [self.q[3], -self.q[2], self.q[1], self.q[0]]]) + + def _q_bar_matrix(self): + """Matrix representation of quaternion for multiplication purposes. + """ + return np.array([ + [self.q[0], -self.q[1], -self.q[2], -self.q[3]], + [self.q[1], self.q[0], self.q[3], -self.q[2]], + [self.q[2], -self.q[3], self.q[0], self.q[1]], + [self.q[3], self.q[2], -self.q[1], self.q[0]]]) + + def _rotate_quaternion(self, q): + """Rotate a quaternion vector using the stored rotation. + + Params: + q: The vector to be rotated, in quaternion form (0 + xi + yj + kz) + + Returns: + A Quaternion object representing the rotated vector in quaternion from (0 + xi + yj + kz) + """ + self._normalise() + return self * q * self.conjugate + + def rotate(self, vector): + """Rotate a 3D vector by the rotation stored in the Quaternion object. + + Params: + vector: A 3-vector specified as any ordered sequence of 3 real numbers corresponding to x, y, and z values. + Some types that are recognised are: numpy arrays, lists and tuples. + A 3-vector can also be represented by a Quaternion object who's scalar part is 0 and vector part is the required 3-vector. + Thus it is possible to call `Quaternion.rotate(q)` with another quaternion object as an input. + + Returns: + The rotated vector returned as the same type it was specified at input. + + Raises: + TypeError: if any of the vector elements cannot be converted to a real number. + ValueError: if `vector` cannot be interpreted as a 3-vector or a Quaternion object. + + """ + if isinstance(vector, Quaternion): + return self._rotate_quaternion(vector) + q = Quaternion(vector=vector) + a = self._rotate_quaternion(q).vector + if isinstance(vector, list): + l = [x for x in a] + return l + elif isinstance(vector, tuple): + l = [x for x in a] + return tuple(l) + else: + return a + + @classmethod + def exp(cls, q): + """Quaternion Exponential. + + Find the exponential of a quaternion amount. + + Params: + q: the input quaternion/argument as a Quaternion object. + + Returns: + A quaternion amount representing the exp(q). See [Source](https://math.stackexchange.com/questions/1030737/exponential-function-of-quaternion-derivation for more information and mathematical background). + + Note: + The method can compute the exponential of any quaternion. + """ + tolerance = 1e-17 + v_norm = np.linalg.norm(q.vector) + vec = q.vector + if v_norm > tolerance: + vec = vec / v_norm + magnitude = exp(q.scalar) + return Quaternion(scalar = magnitude * cos(v_norm), vector = magnitude * sin(v_norm) * vec) + + @classmethod + def log(cls, q): + """Quaternion Logarithm. + + Find the logarithm of a quaternion amount. + + Params: + q: the input quaternion/argument as a Quaternion object. + + Returns: + A quaternion amount representing log(q) := (log(|q|), v/|v|acos(w/|q|)). + + Note: + The method computes the logarithm of general quaternions. See [Source](https://math.stackexchange.com/questions/2552/the-logarithm-of-quaternion/2554#2554) for more details. + """ + v_norm = np.linalg.norm(q.vector) + q_norm = q.norm + tolerance = 1e-17 + if q_norm < tolerance: + # 0 quaternion - undefined + return Quaternion(scalar=-float('inf'), vector=float('nan')*q.vector) + if v_norm < tolerance: + # real quaternions - no imaginary part + return Quaternion(scalar=log(q_norm), vector=[0,0,0]) + vec = q.vector / v_norm + return Quaternion(scalar=log(q_norm), vector=acos(q.scalar/q_norm)*vec) + + @classmethod + def exp_map(cls, q, eta): + """Quaternion exponential map. + + Find the exponential map on the Riemannian manifold described + by the quaternion space. + + Params: + q: the base point of the exponential map, i.e. a Quaternion object + eta: the argument of the exponential map, a tangent vector, i.e. a Quaternion object + + Returns: + A quaternion p such that p is the endpoint of the geodesic starting at q + in the direction of eta, having the length equal to the magnitude of eta. + + Note: + The exponential map plays an important role in integrating orientation + variations (e.g. angular velocities). This is done by projecting + quaternion tangent vectors onto the quaternion manifold. + """ + return q * Quaternion.exp(eta) + + @classmethod + def sym_exp_map(cls, q, eta): + """Quaternion symmetrized exponential map. + + Find the symmetrized exponential map on the quaternion Riemannian + manifold. + + Params: + q: the base point as a Quaternion object + eta: the tangent vector argument of the exponential map + as a Quaternion object + + Returns: + A quaternion p. + + Note: + The symmetrized exponential formulation is akin to the exponential + formulation for symmetric positive definite tensors [Source](http://www.academia.edu/7656761/On_the_Averaging_of_Symmetric_Positive-Definite_Tensors) + """ + sqrt_q = q ** 0.5 + return sqrt_q * Quaternion.exp(eta) * sqrt_q + + @classmethod + def log_map(cls, q, p): + """Quaternion logarithm map. + + Find the logarithm map on the quaternion Riemannian manifold. + + Params: + q: the base point at which the logarithm is computed, i.e. + a Quaternion object + p: the argument of the quaternion map, a Quaternion object + + Returns: + A tangent vector having the length and direction given by the + geodesic joining q and p. + """ + return Quaternion.log(q.inverse * p) + + @classmethod + def sym_log_map(cls, q, p): + """Quaternion symmetrized logarithm map. + + Find the symmetrized logarithm map on the quaternion Riemannian manifold. + + Params: + q: the base point at which the logarithm is computed, i.e. + a Quaternion object + p: the argument of the quaternion map, a Quaternion object + + Returns: + A tangent vector corresponding to the symmetrized geodesic curve formulation. + + Note: + Information on the symmetrized formulations given in [Source](https://www.researchgate.net/publication/267191489_Riemannian_L_p_Averaging_on_Lie_Group_of_Nonzero_Quaternions). + """ + inv_sqrt_q = (q ** (-0.5)) + return Quaternion.log(inv_sqrt_q * p * inv_sqrt_q) + + @classmethod + def absolute_distance(cls, q0, q1): + """Quaternion absolute distance. + + Find the distance between two quaternions accounting for the sign ambiguity. + + Params: + q0: the first quaternion + q1: the second quaternion + + Returns: + A positive scalar corresponding to the chord of the shortest path/arc that + connects q0 to q1. + + Note: + This function does not measure the distance on the hypersphere, but + it takes into account the fact that q and -q encode the same rotation. + It is thus a good indicator for rotation similarities. + """ + q0_minus_q1 = q0 - q1 + q0_plus_q1 = q0 + q1 + d_minus = q0_minus_q1.norm + d_plus = q0_plus_q1.norm + if (d_minus < d_plus): + return d_minus + else: + return d_plus + + @classmethod + def distance(cls, q0, q1): + """Quaternion intrinsic distance. + + Find the intrinsic geodesic distance between q0 and q1. + + Params: + q0: the first quaternion + q1: the second quaternion + + Returns: + A positive amount corresponding to the length of the geodesic arc + connecting q0 to q1. + + Note: + Although the q0^(-1)*q1 != q1^(-1)*q0, the length of the path joining + them is given by the logarithm of those product quaternions, the norm + of which is the same. + """ + q = Quaternion.log_map(q0, q1) + return q.norm + + @classmethod + def sym_distance(cls, q0, q1): + """Quaternion symmetrized distance. + + Find the intrinsic symmetrized geodesic distance between q0 and q1. + + Params: + q0: the first quaternion + q1: the second quaternion + + Returns: + A positive amount corresponding to the length of the symmetrized + geodesic curve connecting q0 to q1. + + Note: + This formulation is more numerically stable when performing + iterative gradient descent on the Riemannian quaternion manifold. + However, the distance between q and -q is equal to pi, rendering this + formulation not useful for measuring rotation similarities when the + samples are spread over a "solid" angle of more than pi/2 radians + (the spread refers to quaternions as point samples on the unit hypersphere). + """ + q = Quaternion.sym_log_map(q0, q1) + return q.norm + + @classmethod + def slerp(cls, q0, q1, amount=0.5): + """Spherical Linear Interpolation between quaternions. + Implemented as described in https://en.wikipedia.org/wiki/Slerp + + Find a valid quaternion rotation at a specified distance along the + minor arc of a great circle passing through any two existing quaternion + endpoints lying on the unit radius hypersphere. + + This is a class method and is called as a method of the class itself rather than on a particular instance. + + Params: + q0: first endpoint rotation as a Quaternion object + q1: second endpoint rotation as a Quaternion object + amount: interpolation parameter between 0 and 1. This describes the linear placement position of + the result along the arc between endpoints; 0 being at `q0` and 1 being at `q1`. + Defaults to the midpoint (0.5). + + Returns: + A new Quaternion object representing the interpolated rotation. This is guaranteed to be a unit quaternion. + + Note: + This feature only makes sense when interpolating between unit quaternions (those lying on the unit radius hypersphere). + Calling this method will implicitly normalise the endpoints to unit quaternions if they are not already unit length. + """ + # Ensure quaternion inputs are unit quaternions and 0 <= amount <=1 + q0._fast_normalise() + q1._fast_normalise() + amount = np.clip(amount, 0, 1) + + dot = np.dot(q0.q, q1.q) + + # If the dot product is negative, slerp won't take the shorter path. + # Note that v1 and -v1 are equivalent when the negation is applied to all four components. + # Fix by reversing one quaternion + if (dot < 0.0): + q0.q = -q0.q + dot = -dot + + # sin_theta_0 can not be zero + if (dot > 0.9995): + qr = Quaternion(q0.q + amount*(q1.q - q0.q)) + qr._fast_normalise() + return qr + + theta_0 = np.arccos(dot) # Since dot is in range [0, 0.9995], np.arccos() is safe + sin_theta_0 = np.sin(theta_0) + + theta = theta_0*amount + sin_theta = np.sin(theta) + + s0 = np.cos(theta) - dot * sin_theta / sin_theta_0 + s1 = sin_theta / sin_theta_0 + qr = Quaternion((s0 * q0.q) + (s1 * q1.q)) + qr._fast_normalise() + return qr + + @classmethod + def intermediates(cls, q0, q1, n, include_endpoints=False): + """Generator method to get an iterable sequence of `n` evenly spaced quaternion + rotations between any two existing quaternion endpoints lying on the unit + radius hypersphere. + + This is a convenience function that is based on `Quaternion.slerp()` as defined above. + + This is a class method and is called as a method of the class itself rather than on a particular instance. + + Params: + q_start: initial endpoint rotation as a Quaternion object + q_end: final endpoint rotation as a Quaternion object + n: number of intermediate quaternion objects to include within the interval + include_endpoints: [optional] if set to `True`, the sequence of intermediates + will be 'bookended' by `q_start` and `q_end`, resulting in a sequence length of `n + 2`. + If set to `False`, endpoints are not included. Defaults to `False`. + + Yields: + A generator object iterating over a sequence of intermediate quaternion objects. + + Note: + This feature only makes sense when interpolating between unit quaternions (those lying on the unit radius hypersphere). + Calling this method will implicitly normalise the endpoints to unit quaternions if they are not already unit length. + """ + step_size = 1.0 / (n + 1) + if include_endpoints: + steps = [i * step_size for i in range(0, n + 2)] + else: + steps = [i * step_size for i in range(1, n + 1)] + for step in steps: + yield cls.slerp(q0, q1, step) + + def derivative(self, rate): + """Get the instantaneous quaternion derivative representing a quaternion rotating at a 3D rate vector `rate` + + Params: + rate: numpy 3-array (or array-like) describing rotation rates about the global x, y and z axes respectively. + + Returns: + A unit quaternion describing the rotation rate + """ + rate = self._validate_number_sequence(rate, 3) + return 0.5 * self * Quaternion(vector=rate) + + def integrate(self, rate, timestep): + """Advance a time varying quaternion to its value at a time `timestep` in the future. + + The Quaternion object will be modified to its future value. + It is guaranteed to remain a unit quaternion. + + Params: + + rate: numpy 3-array (or array-like) describing rotation rates about the + global x, y and z axes respectively. + timestep: interval over which to integrate into the future. + Assuming *now* is `T=0`, the integration occurs over the interval + `T=0` to `T=timestep`. Smaller intervals are more accurate when + `rate` changes over time. + + Note: + The solution is closed form given the assumption that `rate` is constant + over the interval of length `timestep`. + """ + self._fast_normalise() + rate = self._validate_number_sequence(rate, 3) + + rotation_vector = rate * timestep + rotation_norm = np.linalg.norm(rotation_vector) + if rotation_norm > 0: + axis = rotation_vector / rotation_norm + angle = rotation_norm + q2 = Quaternion(axis=axis, angle=angle) + self.q = (self * q2).q + self._fast_normalise() + + + @property + def rotation_matrix(self): + """Get the 3x3 rotation matrix equivalent of the quaternion rotation. + + Returns: + A 3x3 orthogonal rotation matrix as a 3x3 Numpy array + + Note: + This feature only makes sense when referring to a unit quaternion. Calling this method will implicitly normalise the Quaternion object to a unit quaternion if it is not already one. + + """ + self._normalise() + product_matrix = np.dot(self._q_matrix(), self._q_bar_matrix().conj().transpose()) + return product_matrix[1:][:,1:] + + @property + def transformation_matrix(self): + """Get the 4x4 homogeneous transformation matrix equivalent of the quaternion rotation. + + Returns: + A 4x4 homogeneous transformation matrix as a 4x4 Numpy array + + Note: + This feature only makes sense when referring to a unit quaternion. Calling this method will implicitly normalise the Quaternion object to a unit quaternion if it is not already one. + """ + t = np.array([[0.0], [0.0], [0.0]]) + Rt = np.hstack([self.rotation_matrix, t]) + return np.vstack([Rt, np.array([0.0, 0.0, 0.0, 1.0])]) + + @property + def yaw_pitch_roll(self): + """Get the equivalent yaw-pitch-roll angles aka. intrinsic Tait-Bryan angles following the z-y'-x'' convention + + Returns: + yaw: rotation angle around the z-axis in radians, in the range `[-pi, pi]` + pitch: rotation angle around the y'-axis in radians, in the range `[-pi/2, -pi/2]` + roll: rotation angle around the x''-axis in radians, in the range `[-pi, pi]` + + The resulting rotation_matrix would be R = R_x(roll) R_y(pitch) R_z(yaw) + + Note: + This feature only makes sense when referring to a unit quaternion. Calling this method will implicitly normalise the Quaternion object to a unit quaternion if it is not already one. + """ + + self._normalise() + yaw = np.arctan2(2*(self.q[0]*self.q[3] - self.q[1]*self.q[2]), + 1 - 2*(self.q[2]**2 + self.q[3]**2)) + pitch = np.arcsin(2*(self.q[0]*self.q[2] + self.q[3]*self.q[1])) + roll = np.arctan2(2*(self.q[0]*self.q[1] - self.q[2]*self.q[3]), + 1 - 2*(self.q[1]**2 + self.q[2]**2)) + + return yaw, pitch, roll + + def _wrap_angle(self, theta): + """Helper method: Wrap any angle to lie between -pi and pi + + Odd multiples of pi are wrapped to +pi (as opposed to -pi) + """ + result = ((theta + pi) % (2*pi)) - pi + if result == -pi: result = pi + return result + + def get_axis(self, undefined=np.zeros(3)): + """Get the axis or vector about which the quaternion rotation occurs + + For a null rotation (a purely real quaternion), the rotation angle will + always be `0`, but the rotation axis is undefined. + It is by default assumed to be `[0, 0, 0]`. + + Params: + undefined: [optional] specify the axis vector that should define a null rotation. + This is geometrically meaningless, and could be any of an infinite set of vectors, + but can be specified if the default (`[0, 0, 0]`) causes undesired behaviour. + + Returns: + A Numpy unit 3-vector describing the Quaternion object's axis of rotation. + + Note: + This feature only makes sense when referring to a unit quaternion. + Calling this method will implicitly normalise the Quaternion object to a unit quaternion if it is not already one. + """ + tolerance = 1e-17 + self._normalise() + norm = np.linalg.norm(self.vector) + if norm < tolerance: + # Here there are an infinite set of possible axes, use what has been specified as an undefined axis. + return undefined + else: + return self.vector / norm + + @property + def axis(self): + return self.get_axis() + + @property + def angle(self): + """Get the angle (in radians) describing the magnitude of the quaternion rotation about its rotation axis. + + This is guaranteed to be within the range (-pi:pi) with the direction of + rotation indicated by the sign. + + When a particular rotation describes a 180 degree rotation about an arbitrary + axis vector `v`, the conversion to axis / angle representation may jump + discontinuously between all permutations of `(-pi, pi)` and `(-v, v)`, + each being geometrically equivalent (see Note in documentation). + + Returns: + A real number in the range (-pi:pi) describing the angle of rotation + in radians about a Quaternion object's axis of rotation. + + Note: + This feature only makes sense when referring to a unit quaternion. + Calling this method will implicitly normalise the Quaternion object to a unit quaternion if it is not already one. + """ + self._normalise() + norm = np.linalg.norm(self.vector) + return self._wrap_angle(2.0 * atan2(norm,self.scalar)) + + @property + def degrees(self): + return self.to_degrees(self.angle) + + @property + def radians(self): + return self.angle + + @property + def scalar(self): + """ Return the real or scalar component of the quaternion object. + + Returns: + A real number i.e. float + """ + return self.q[0] + + @property + def vector(self): + """ Return the imaginary or vector component of the quaternion object. + + Returns: + A numpy 3-array of floats. NOT guaranteed to be a unit vector + """ + return self.q[1:4] + + @property + def real(self): + return self.scalar + + @property + def imaginary(self): + return self.vector + + @property + def w(self): + return self.q[0] + + @property + def x(self): + return self.q[1] + + @property + def y(self): + return self.q[2] + + @property + def z(self): + return self.q[3] + + @property + def elements(self): + """ Return all the elements of the quaternion object. + + Returns: + A numpy 4-array of floats. NOT guaranteed to be a unit vector + """ + return self.q + + def __getitem__(self, index): + index = int(index) + return self.q[index] + + def __setitem__(self, index, value): + index = int(index) + self.q[index] = float(value) + + def __copy__(self): + result = self.__class__(self.q) + return result + + def __deepcopy__(self, memo): + result = self.__class__(deepcopy(self.q, memo)) + memo[id(self)] = result + return result + + @staticmethod + def to_degrees(angle_rad): + if angle_rad is not None: + return float(angle_rad) / pi * 180.0 + + @staticmethod + def to_radians(angle_deg): + if angle_deg is not None: + return float(angle_deg) / 180.0 * pi diff --git a/vtk_py/pyquaternion/quaternion.pyc b/vtk_py/pyquaternion/quaternion.pyc new file mode 100644 index 0000000..ac2528d Binary files /dev/null and b/vtk_py/pyquaternion/quaternion.pyc differ diff --git a/vtk_py/readAbaqusDeformationGradients.py b/vtk_py/readAbaqusDeformationGradients.py new file mode 100644 index 0000000..2b4d6ac --- /dev/null +++ b/vtk_py/readAbaqusDeformationGradients.py @@ -0,0 +1,45 @@ +######################################################################## + +import numpy +import vtk + +######################################################################## + +def readAbaqusDeformationGradients(data_file_name, + verbose=True): + + if (verbose): print '*** readAbaqusDeformationGradients ***' + + F_array = createFloatArray("F", 9) + + data_file = open(data_file_name, 'r') + context = "" + num_cell = 0 + for line in data_file: + if (context == "reading deformation gradients"): + #print line + if ("MAXIMUM" in line): + context = "" + continue + if ("OR" in line): + splitted_line = line.split() + assert (int(splitted_line[0]) == num_cell+1), "Wrong element number. Aborting." + F_list = [float(splitted_line[ 3]), float(splitted_line[ 6]), float(splitted_line[7]), + float(splitted_line[ 9]), float(splitted_line[ 4]), float(splitted_line[8]), + float(splitted_line[10]), float(splitted_line[11]), float(splitted_line[5])] + F_array.InsertNextTuple(F_list) + num_cell += 1 + + if (line == " ELEMENT PT FOOT- DG11 DG22 DG33 DG12 DG13 DG23 DG21 DG31 DG32 \n"): + context = "reading deformation gradients" + + data_file.close() + + if (verbose): print "nb_tuples = " + str(F_array.GetNumberOfTuples()) + + return F_array + + + + + diff --git a/vtk_py/readAbaqusDeformationGradients.pyc b/vtk_py/readAbaqusDeformationGradients.pyc new file mode 100644 index 0000000..6f3669b Binary files /dev/null and b/vtk_py/readAbaqusDeformationGradients.pyc differ diff --git a/vtk_py/readAbaqusMesh.py b/vtk_py/readAbaqusMesh.py new file mode 100644 index 0000000..83da9c6 --- /dev/null +++ b/vtk_py/readAbaqusMesh.py @@ -0,0 +1,72 @@ +######################################################################## + +import vtk + +######################################################################## + +def readAbaqusMesh(mesh_filename, + elem_types="all", + verbose=True): + + if (verbose): print "*** readAbaqusMesh ***" + + points = vtk.vtkPoints() + cell_array = vtk.vtkCellArray() + + mesh_file = open(mesh_filename, "r") + + context = "" + for line in mesh_file: + if (line[-1:] == "\n"): line = line[:-1] + #if (verbose): print "line =", line + + if line.startswith("**"): continue + + if (context == "reading nodes"): + if line.startswith("*"): + context = "" + else: + splitted_line = line.split(",") + points.InsertNextPoint([float(coord) for coord in splitted_line[1:4]]) + + if (context == "reading elems"): + if line.startswith("*"): + context = "" + else: + splitted_line = line.split(",") + assert (len(splitted_line) == 1+cell_nb_points), "Wrong number of elements in line. Aborting." + for num_point in range(cell_nb_points): cell.GetPointIds().SetId(num_point, int(splitted_line[1+num_point])-1) + cell_array.InsertNextCell(cell) + + if line.startswith("*NODE"): + context = "reading nodes" + if line.startswith("*ELEMENT"): + if ("TYPE=F3D4" in line) and (("quad" in elem_types) or ("all" in elem_types)): + context = "reading elems" + cell_vtk_type = vtk.VTK_QUAD + cell_nb_points = 4 + cell = vtk.vtkQuad() + elif ("TYPE=C3D4" in line) and (("tet" in elem_types) or ("all" in elem_types)): + context = "reading elems" + cell_vtk_type = vtk.VTK_TETRA + cell_nb_points = 4 + cell = vtk.vtkTetra() + elif ("TYPE=C3D8" in line) and (("hex" in elem_types) or ("all" in elem_types)): + context = "reading elems" + cell_vtk_type = vtk.VTK_HEXAHEDRON + cell_nb_points = 8 + cell = vtk.vtkHexahedron() + else: + print "Warning: element type not taken into account." + + mesh_file.close() + + if (verbose): print "Creating UGrid..." + + ugrid = vtk.vtkUnstructuredGrid() + ugrid.SetPoints(points) + ugrid.SetCells(cell_vtk_type, cell_array) + + if (verbose): print "nb_cells = " + str(ugrid.GetNumberOfCells()) + + return ugrid diff --git a/vtk_py/readAbaqusMesh.pyc b/vtk_py/readAbaqusMesh.pyc new file mode 100644 index 0000000..2a31032 Binary files /dev/null and b/vtk_py/readAbaqusMesh.pyc differ diff --git a/vtk_py/readAbaqusStresses.py b/vtk_py/readAbaqusStresses.py new file mode 100644 index 0000000..6246adf --- /dev/null +++ b/vtk_py/readAbaqusStresses.py @@ -0,0 +1,43 @@ +######################################################################## + +import numpy +import vtk + +######################################################################## + +def readAbaqusStress(data_file_name, + verbose=True): + + if (verbose): print '*** readAbaqusStress ***' + + s_array = createFloatArray("", 6) + + data_file = open(data_file_name, 'r') + context = "" + num_cell = 0 + for line in data_file: + if (context == "reading stresses"): + #print line + if ("MAXIMUM" in line): + context = "" + continue + if ("OR" in line): + splitted_line = line.split() + assert (int(splitted_line[0]) == num_cell+1), "Wrong element number. Aborting." + s_list = [float(splitted_line[k]) for k in range(3,9)] + s_array.InsertNextTuple(s_list) + num_cell += 1 + + if (line == " ELEMENT PT FOOT- S11 S22 S33 S12 S13 S23 \n"): + context = "reading stresses" + + data_file.close() + + if (verbose): print "nb_tuples = " + str(s_array.GetNumberOfTuples()) + + return s_array + + + + + diff --git a/vtk_py/readAbaqusStresses.pyc b/vtk_py/readAbaqusStresses.pyc new file mode 100644 index 0000000..7f62417 Binary files /dev/null and b/vtk_py/readAbaqusStresses.pyc differ diff --git a/vtk_py/readDynaDeformationGradients.py b/vtk_py/readDynaDeformationGradients.py new file mode 100644 index 0000000..6430ec3 --- /dev/null +++ b/vtk_py/readDynaDeformationGradients.py @@ -0,0 +1,38 @@ +######################################################################## + +import numpy +import vtk + +from createFloatArray import * + +######################################################################## + +def readDynaDeformationGradients(mesh, + hystory_files_basename, + array_name, + verbose=True): + + if (verbose): print '*** readDynaDeformationGradients ***' + + nb_cells = mesh.GetNumberOfCells() + + history_files_names = [hystory_files_basename + '.history#' + str(num) for num in range(11,20)] + + F_list = [[0. for num_component in range(9)] for num_cell in range(nb_cells)] + + for num_component in range(9): + history_file = open(history_files_names[num_component], 'r') + for line in history_file: + if line.startswith('*') or line.startswith('$'): continue + line = line.split() + F_list[int(line[0])-1][num_component] = float(line[1]) + history_file.close() + + F_array = createFloatArray(array_name, 9, nb_cells) + + for num_cell in range(nb_cells): + F_array.InsertTuple(num_cell, F_list[num_cell]) + + if (verbose): print "nb_tuples = " + str(F_array.GetNumberOfTuples()) + + mesh.GetCellData().AddArray(F_array) diff --git a/vtk_py/readDynaDeformationGradients.pyc b/vtk_py/readDynaDeformationGradients.pyc new file mode 100644 index 0000000..9c428ff Binary files /dev/null and b/vtk_py/readDynaDeformationGradients.pyc differ diff --git a/vtk_py/readDynaDeformationGradients_vtk.py b/vtk_py/readDynaDeformationGradients_vtk.py new file mode 100644 index 0000000..c9222cf --- /dev/null +++ b/vtk_py/readDynaDeformationGradients_vtk.py @@ -0,0 +1,64 @@ +######################################################################## + +import numpy +import vtk + +from createFloatArray import * + +######################################################################## + +def readDynaDeformationGradients_vtk(mesh, + hystory_files_basename, + array_name, ES_timept, + verbose=True): + + if (verbose): print '*** readDynaDeformationGradients ***' + + nb_cells = mesh.GetNumberOfCells() + + reader = vtk.vtkLSDynaReader() + reader.SetDatabaseDirectory('./') + reader.SetTimeStep(ES_timept) + reader.Update() + + print nb_cells, reader.GetNumberOfSolidCells() + + F11 = vtk.vtkDoubleArray() + F12 = vtk.vtkDoubleArray() + F13 = vtk.vtkDoubleArray() + F21 = vtk.vtkDoubleArray() + F22 = vtk.vtkDoubleArray() + F23 = vtk.vtkDoubleArray() + F31 = vtk.vtkDoubleArray() + F32 = vtk.vtkDoubleArray() + F33 = vtk.vtkDoubleArray() + + + + numtuples = reader.GetOutput().GetBlock(0).GetCellData().GetArray('IntPtData').GetNumberOfTuples() + reader.GetOutput().GetBlock(0).GetCellData().GetArray('IntPtData').GetData(0, numtuples-1, 10, 10, F11) + reader.GetOutput().GetBlock(0).GetCellData().GetArray('IntPtData').GetData(0, numtuples-1, 11, 11, F12) + reader.GetOutput().GetBlock(0).GetCellData().GetArray('IntPtData').GetData(0, numtuples-1, 12, 12, F13) + reader.GetOutput().GetBlock(0).GetCellData().GetArray('IntPtData').GetData(0, numtuples-1, 13, 13, F21) + reader.GetOutput().GetBlock(0).GetCellData().GetArray('IntPtData').GetData(0, numtuples-1, 14, 14, F22) + reader.GetOutput().GetBlock(0).GetCellData().GetArray('IntPtData').GetData(0, numtuples-1, 15, 15, F23) + reader.GetOutput().GetBlock(0).GetCellData().GetArray('IntPtData').GetData(0, numtuples-1, 16, 16, F31) + reader.GetOutput().GetBlock(0).GetCellData().GetArray('IntPtData').GetData(0, numtuples-1, 17, 17, F32) + reader.GetOutput().GetBlock(0).GetCellData().GetArray('IntPtData').GetData(0, numtuples-1, 18, 18, F33) + + F_array = createFloatArray(array_name, 9, nb_cells) + + for num_cell in range(nb_cells): + F_list = [F11.GetValue(num_cell), F12.GetValue(num_cell), F13.GetValue(num_cell), + F21.GetValue(num_cell), F22.GetValue(num_cell), F23.GetValue(num_cell), + F31.GetValue(num_cell), F32.GetValue(num_cell), F33.GetValue(num_cell)] + F_array.InsertTuple(num_cell, F_list) + + + if (verbose): print "nb_tuples = " + str(F_array.GetNumberOfTuples()) + + mesh.GetCellData().AddArray(F_array) + + + + diff --git a/vtk_py/readDynaDeformationGradients_vtk.pyc b/vtk_py/readDynaDeformationGradients_vtk.pyc new file mode 100644 index 0000000..171c569 Binary files /dev/null and b/vtk_py/readDynaDeformationGradients_vtk.pyc differ diff --git a/vtk_py/readDynaMesh.py b/vtk_py/readDynaMesh.py new file mode 100644 index 0000000..e885ca9 --- /dev/null +++ b/vtk_py/readDynaMesh.py @@ -0,0 +1,101 @@ +######################################################################## + +import vtk + +######################################################################## + +def readDynaMesh(lsdyna_mesh_file_name, cell_type='hexahedron', verbose=True, filetype='post'): + + if (verbose): print '*** readDynaMesh ***' + + points = vtk.vtkPoints() + + if (cell_type == 'vertex'): + cell_vtk_type = vtk.VTK_VERTEX + cell = vtk.vtkVertex() + cell_array = vtk.vtkCellArray() + elif (cell_type == 'hexahedron'): + cell_vtk_type = vtk.VTK_HEXAHEDRON + cell = vtk.vtkHexahedron() + cell_array = vtk.vtkCellArray() + matid_array = vtk.vtkIntArray() + matid_array.SetName("matid") + fiber_array = vtk.vtkFloatArray() + fiber_array.SetNumberOfComponents(3) + fiber_array.SetName("fvec") + sheet_array = vtk.vtkFloatArray() + sheet_array.SetNumberOfComponents(3) + sheet_array.SetName("svec") + else: + print 'Wrong cell type. Aborting.' + exit() + + if (verbose): print 'Reading Dyna mesh file...' + + mesh_file = open(lsdyna_mesh_file_name, 'r') + + context = '' + isfiber = False + issheet = False + for line in mesh_file: + if (line[-1:] == '\n'): line = line[:-1] + #if (verbose): print 'line =', line + + if line.startswith('$'): continue + + if (context == 'reading nodes'): + if line.startswith('*'): + context = '' + else: + splitted_line = line.split(',') + points.InsertNextPoint([float(coord) for coord in splitted_line[1:4]]) + if (cell_type == 'vertex'): + cell.GetPointIds().SetId(0, points.GetNumberOfPoints()-1) + cell_array.InsertNextCell(cell) + + if (context == 'reading elems'): + if line.startswith('*'): + context = '' + else: + splitted_line = line.split(',') + + if(filetype == 'post'): + if (len(splitted_line) == 3 and isfiber == True): + fiber_array.InsertNextTuple3(float(splitted_line[0]), float(splitted_line[1]), float(splitted_line[2])) + isfiber = False; issheet = True; + elif (len(splitted_line) == 3 and issheet == True): + sheet_array.InsertNextTuple3(float(splitted_line[0]), float(splitted_line[1]), float(splitted_line[2])) + isfiber = False; issheet = False; + + if (len(splitted_line) != 3): + matid_array.InsertNextValue(int(splitted_line[1])) + for num_node in range(8): + cell.GetPointIds().SetId(num_node, int(splitted_line[2+num_node])-1) + isfiber = True; + cell_array.InsertNextCell(cell) + + elif(filetype == 'pre'): + + matid_array.InsertNextValue(int(splitted_line[1])) + for num_node in range(8): + cell.GetPointIds().SetId(num_node, int(splitted_line[2+num_node])-1) + isfiber = True; + cell_array.InsertNextCell(cell) + + + if line.startswith('*NODE'): context = 'reading nodes' + if line.startswith('*ELEMENT_SOLID'): context = 'reading elems' + + mesh_file.close() + + if (verbose): print 'Creating VTK mesh...' + + ugrid = vtk.vtkUnstructuredGrid() + ugrid.SetPoints(points) + ugrid.SetCells(cell_vtk_type, cell_array) + ugrid.GetCellData().AddArray(matid_array) + if(filetype == 'post'): + ugrid.GetCellData().AddArray(fiber_array) + ugrid.GetCellData().AddArray(sheet_array) + + return ugrid diff --git a/vtk_py/readDynaMesh.pyc b/vtk_py/readDynaMesh.pyc new file mode 100644 index 0000000..e9e3b87 Binary files /dev/null and b/vtk_py/readDynaMesh.pyc differ diff --git a/vtk_py/readDynaMeshStructured.py b/vtk_py/readDynaMeshStructured.py new file mode 100644 index 0000000..df67644 --- /dev/null +++ b/vtk_py/readDynaMeshStructured.py @@ -0,0 +1,90 @@ +######################################################################## + +import vtk +import math + +######################################################################## + +def readDynaMeshStructured(lsdyna_mesh_file_name, cell_type='hexahedron', verbose=True): + + if (verbose): print '*** readDynaMesh ***' + + points = vtk.vtkPoints() + + if (cell_type == 'vertex'): + cell_vtk_type = vtk.VTK_VERTEX + cell = vtk.vtkVertex() + cell_array = vtk.vtkCellArray() + elif (cell_type == 'hexahedron'): + cell_vtk_type = vtk.VTK_HEXAHEDRON + cell = vtk.vtkHexahedron() + cell_array = vtk.vtkCellArray() + else: + print 'Wrong cell type. Aborting.' + exit() + + if (verbose): print 'Reading Dyna mesh file...' + + cnt = 1; + + mesh_file = open(lsdyna_mesh_file_name, 'r') + + context = '' + for line in mesh_file: + if (line[-1:] == '\n'): line = line[:-1] + #if (verbose): print 'line =', line + + if line.startswith('$'): continue + + if (context == 'reading nodes'): + if line.startswith('*'): + context = '' + else: + #splitted_line = line.split(',') + splitted_line = [] + splitted_line.append(line[0:8].replace(" ","")) + splitted_line.append(line[8:24].replace(" ","")) + splitted_line.append(line[25:25+16].replace(" ","")) + splitted_line.append(line[25+17:50+17].replace(" ","")) + print splitted_line + + points.InsertNextPoint([float(coord) for coord in splitted_line[1:4]]) + if (cell_type == 'vertex'): + cell.GetPointIds().SetId(0, points.GetNumberOfPoints()-1) + cell_array.InsertNextCell(cell) + + if (context == 'reading elems'): + if line.startswith('*'): + context = '' + else: + if(cnt%2 == 0): + + splitted_line = [] + splitted_line.append(line[0:8].replace(" ","")) + splitted_line.append(line[9:16].replace(" ","")) + splitted_line.append(line[17:24].replace(" ","")) + splitted_line.append(line[25:32].replace(" ","")) + splitted_line.append(line[33:40].replace(" ","")) + splitted_line.append(line[41:48].replace(" ","")) + splitted_line.append(line[49:56].replace(" ","")) + splitted_line.append(line[57:64].replace(" ","")) + if (len(splitted_line) == 3): continue + if (cell_type == 'hexahedron'): + for num_node in range(8): + cell.GetPointIds().SetId(num_node, int(splitted_line[num_node])-1) + cell_array.InsertNextCell(cell) + + cnt = cnt + 1; + + if line.startswith('*NODE'): context = 'reading nodes' + if line.startswith('*ELEMENT_SOLID'): context = 'reading elems' + + mesh_file.close() + + if (verbose): print 'Creating VTK mesh...' + + ugrid = vtk.vtkUnstructuredGrid() + ugrid.SetPoints(points) + ugrid.SetCells(cell_vtk_type, cell_array) + + return ugrid diff --git a/vtk_py/readDynaMeshStructured.pyc b/vtk_py/readDynaMeshStructured.pyc new file mode 100644 index 0000000..e90962e Binary files /dev/null and b/vtk_py/readDynaMeshStructured.pyc differ diff --git a/vtk_py/readFiberOrientation.py b/vtk_py/readFiberOrientation.py new file mode 100644 index 0000000..a3675f9 --- /dev/null +++ b/vtk_py/readFiberOrientation.py @@ -0,0 +1,52 @@ +######################################################################## + +import numpy +import vtk + +from createFloatArray import * + +######################################################################## + +def readFiberOrientation(mesh, + filename, + verbose=True): + + if (verbose): print '*** readFiberOrientation ***' + + nb_cells = mesh.GetNumberOfCells() + + if verbose: print 'Reading fiber orientations...' + + eF_array = createFloatArray('eF', 3, nb_cells) + eS_array = createFloatArray('eS', 3, nb_cells) + eN_array = createFloatArray('eN', 3, nb_cells) + + file = open(filename, 'r') + file.readline() + + num_cell = 0 + for line in file: + line = line.split(', ') + #print line + + eF = [float(item) for item in line[1:4]] + eS = [float(item) for item in line[4:7]] + eN = numpy.cross(eF,eS) + #print "eF =", eF + #print "eS =", eS + #print "eN =", eN + + eF_array.InsertTuple(num_cell, eF) + eS_array.InsertTuple(num_cell, eS) + eN_array.InsertTuple(num_cell, eN) + + num_cell += 1 + #print "num_cell =", num_cell + + file.close() + + mesh.GetCellData().AddArray(eF_array) + mesh.GetCellData().AddArray(eS_array) + mesh.GetCellData().AddArray(eN_array) + + return mesh diff --git a/vtk_py/readFiberOrientation.pyc b/vtk_py/readFiberOrientation.pyc new file mode 100644 index 0000000..b4fb446 Binary files /dev/null and b/vtk_py/readFiberOrientation.pyc differ diff --git a/vtk_py/readMSHGrid.py b/vtk_py/readMSHGrid.py new file mode 100644 index 0000000..1244b91 --- /dev/null +++ b/vtk_py/readMSHGrid.py @@ -0,0 +1,69 @@ +######################################################################## + +import numpy +import vtk + +######################################################################## + +def readMSHGrid(mshfilename): + + fdata = open(mshfilename, "r") + lines = fdata.readlines() + startelem = 0 + startnode = 0 + cnt = 0 + + cellArray = vtk.vtkCellArray() + points = vtk.vtkPoints() + for line in lines: + if("$Elements" in line): + startelem = 1 + continue + + if("$EndElements" in line): + startelem = 0 + continue + + if("$Nodes" in line): + startnode = 1 + continue + + if("$EndNodes" in line): + startnode = 0 + continue + + if(startnode == 1): + try: + x = float(line.strip().split()[1]) + y = float(line.strip().split()[2]) + z = float(line.strip().split()[3]) + + points.InsertNextPoint(x, y, z) + + except IndexError: + continue + + + if(startelem == 1): + try: + elmtype = int(line.strip().split()[1]) + if(elmtype == 4): + tetra = vtk.vtkTetra() + tetra.GetPointIds().SetId(0, int(line.strip().split()[5])-1) + tetra.GetPointIds().SetId(1, int(line.strip().split()[6])-1) + tetra.GetPointIds().SetId(2, int(line.strip().split()[7])-1) + tetra.GetPointIds().SetId(3, int(line.strip().split()[8])-1) + cellArray.InsertNextCell(tetra) + except IndexError: + continue + + ugrid = vtk.vtkUnstructuredGrid() + ugrid.SetPoints(points) + ugrid.SetCells(10, cellArray) + + #writeUGrid(ugrid, "test.vtk") + + return ugrid + + + diff --git a/vtk_py/readMSHGrid.pyc b/vtk_py/readMSHGrid.pyc new file mode 100644 index 0000000..eba24ad Binary files /dev/null and b/vtk_py/readMSHGrid.pyc differ diff --git a/vtk_py/readPData.py b/vtk_py/readPData.py new file mode 100644 index 0000000..6ec0cc8 --- /dev/null +++ b/vtk_py/readPData.py @@ -0,0 +1,22 @@ +######################################################################## + +import vtk + +######################################################################## + +def readPData(pdata_file_name, verbose=True): + if (verbose): print '*** readPData ***' + + pdata_reader = vtk.vtkPolyDataReader() + pdata_reader.SetFileName(pdata_file_name) + pdata_reader.Update() + pdata = pdata_reader.GetOutput() + + if (verbose): + print "nb_points = " + str(pdata.GetNumberOfPoints()) + print "nb_verts = " + str(pdata.GetNumberOfVerts()) + print "nb_lines = " + str(pdata.GetNumberOfLines()) + print "nb_polys = " + str(pdata.GetNumberOfPolys()) + print "nb_strips = " + str(pdata.GetNumberOfStrips()) + + return pdata diff --git a/vtk_py/readPData.pyc b/vtk_py/readPData.pyc new file mode 100644 index 0000000..876265f Binary files /dev/null and b/vtk_py/readPData.pyc differ diff --git a/vtk_py/readPLY.py b/vtk_py/readPLY.py new file mode 100644 index 0000000..3d41962 --- /dev/null +++ b/vtk_py/readPLY.py @@ -0,0 +1,22 @@ +######################################################################## + +import vtk + +######################################################################## + +def readPLY(mesh_file_name, verbose=True): + if (verbose): print '*** readSTL ***' + + mesh_reader = vtk.vtkPLYReader() + mesh_reader.SetFileName(mesh_file_name) + mesh_reader.Update() + mesh = mesh_reader.GetOutput() + + if (verbose): + nb_points = mesh.GetNumberOfPoints() + print 'nb_points =', nb_points + + nb_cells = mesh.GetNumberOfCells() + print 'nb_cells =', nb_cells + + return mesh diff --git a/vtk_py/readPLY.pyc b/vtk_py/readPLY.pyc new file mode 100644 index 0000000..deb24b5 Binary files /dev/null and b/vtk_py/readPLY.pyc differ diff --git a/vtk_py/readSTL.py b/vtk_py/readSTL.py new file mode 100644 index 0000000..cb2c8a9 --- /dev/null +++ b/vtk_py/readSTL.py @@ -0,0 +1,22 @@ +######################################################################## + +import vtk + +######################################################################## + +def readSTL(mesh_file_name, verbose=True): + if (verbose): print '*** readSTL ***' + + mesh_reader = vtk.vtkSTLReader() + mesh_reader.SetFileName(mesh_file_name) + mesh_reader.Update() + mesh = mesh_reader.GetOutput() + + if (verbose): + nb_points = mesh.GetNumberOfPoints() + print 'nb_points =', nb_points + + nb_cells = mesh.GetNumberOfCells() + print 'nb_cells =', nb_cells + + return mesh diff --git a/vtk_py/readSTL.pyc b/vtk_py/readSTL.pyc new file mode 100644 index 0000000..3b4114d Binary files /dev/null and b/vtk_py/readSTL.pyc differ diff --git a/vtk_py/readUGrid.py b/vtk_py/readUGrid.py new file mode 100644 index 0000000..9acbd53 --- /dev/null +++ b/vtk_py/readUGrid.py @@ -0,0 +1,22 @@ +######################################################################## + +import vtk + +######################################################################## + +def readUGrid(mesh_file_name, verbose=True): + if (verbose): print '*** readUGrid ***' + + mesh_reader = vtk.vtkUnstructuredGridReader() + mesh_reader.SetFileName(mesh_file_name) + mesh_reader.Update() + mesh = mesh_reader.GetOutput() + + if (verbose): + nb_points = mesh.GetNumberOfPoints() + print 'nb_points =', nb_points + + nb_cells = mesh.GetNumberOfCells() + print 'nb_cells =', nb_cells + + return mesh diff --git a/vtk_py/readUGrid.pyc b/vtk_py/readUGrid.pyc new file mode 100644 index 0000000..391d2a9 Binary files /dev/null and b/vtk_py/readUGrid.pyc differ diff --git a/vtk_py/readVTI.py b/vtk_py/readVTI.py new file mode 100644 index 0000000..ea95463 --- /dev/null +++ b/vtk_py/readVTI.py @@ -0,0 +1,22 @@ +######################################################################## + +import vtk + +######################################################################## + +def readVTI(vti_file_name, verbose=True): + if (verbose): print 'Reading VTK XML mesh...' + + image = vtk.vtkImageData() + image_reader = vtk.vtkXMLImageDataReader() + image_reader.SetFileName(vti_file_name) + image_reader.Update() + + image.DeepCopy(image_reader.GetOutput()) + + if (verbose): + nb_cells = image.GetNumberOfCells() + print 'nb_cells =', nb_cells + + return image + diff --git a/vtk_py/readVTI.pyc b/vtk_py/readVTI.pyc new file mode 100644 index 0000000..9ee042d Binary files /dev/null and b/vtk_py/readVTI.pyc differ diff --git a/vtk_py/readXMLImage.py b/vtk_py/readXMLImage.py new file mode 100644 index 0000000..aed2277 --- /dev/null +++ b/vtk_py/readXMLImage.py @@ -0,0 +1,18 @@ +######################################################################## + +import vtk + +######################################################################## + +def readXMLImage(image_file_name, verbose=True): + if (verbose): print '*** readXMLImage ***' + + image_reader = vtk.vtkXMLImageDataReader() + image_reader.SetFileName(image_file_name) + image_reader.Update() + image = image_reader.GetOutput() + + if (verbose): + print "nb_points = " + str(image.GetNumberOfPoints()) + + return image diff --git a/vtk_py/readXMLImage.pyc b/vtk_py/readXMLImage.pyc new file mode 100644 index 0000000..aa00e18 Binary files /dev/null and b/vtk_py/readXMLImage.pyc differ diff --git a/vtk_py/readXMLPData.py b/vtk_py/readXMLPData.py new file mode 100644 index 0000000..31b3040 --- /dev/null +++ b/vtk_py/readXMLPData.py @@ -0,0 +1,22 @@ +######################################################################## + +import vtk + +######################################################################## + +def readXMLPData(pdata_file_name, verbose=True): + if (verbose): print '*** readXMLPData ***' + + pdata_reader = vtk.vtkXMLPolyDataReader() + pdata_reader.SetFileName(pdata_file_name) + pdata_reader.Update() + pdata = pdata_reader.GetOutput() + + if (verbose): + print "nb_points = " + str(pdata.GetNumberOfPoints()) + print "nb_verts = " + str(pdata.GetNumberOfVerts()) + print "nb_lines = " + str(pdata.GetNumberOfLines()) + print "nb_polys = " + str(pdata.GetNumberOfPolys()) + print "nb_strips = " + str(pdata.GetNumberOfStrips()) + + return pdata diff --git a/vtk_py/readXMLPData.pyc b/vtk_py/readXMLPData.pyc new file mode 100644 index 0000000..eda78b1 Binary files /dev/null and b/vtk_py/readXMLPData.pyc differ diff --git a/vtk_py/readXMLPUGrid.py b/vtk_py/readXMLPUGrid.py new file mode 100644 index 0000000..2d0ec9c --- /dev/null +++ b/vtk_py/readXMLPUGrid.py @@ -0,0 +1,22 @@ +######################################################################## + +import vtk + +######################################################################## + +def readXMLPUGrid(mesh_file_name, verbose=True): + if (verbose): print '*** readXMLPUGrid ***' + + mesh_reader = vtk.vtkXMLPUnstructuredGridReader() + mesh_reader.SetFileName(mesh_file_name) + mesh_reader.Update() + mesh = mesh_reader.GetOutput() + + if (verbose): + nb_points = mesh.GetNumberOfPoints() + print 'nb_points =', nb_points + + nb_cells = mesh.GetNumberOfCells() + print 'nb_cells =', nb_cells + + return mesh diff --git a/vtk_py/readXMLPUGrid.pyc b/vtk_py/readXMLPUGrid.pyc new file mode 100644 index 0000000..39eb0db Binary files /dev/null and b/vtk_py/readXMLPUGrid.pyc differ diff --git a/vtk_py/readXMLUGrid.py b/vtk_py/readXMLUGrid.py new file mode 100644 index 0000000..117ed8e --- /dev/null +++ b/vtk_py/readXMLUGrid.py @@ -0,0 +1,22 @@ +######################################################################## + +import vtk + +######################################################################## + +def readXMLUGrid(mesh_file_name, verbose=True): + if (verbose): print '*** readXMLUGrid ***' + + mesh_reader = vtk.vtkXMLUnstructuredGridReader() + mesh_reader.SetFileName(mesh_file_name) + mesh_reader.Update() + mesh = mesh_reader.GetOutput() + + if (verbose): + nb_points = mesh.GetNumberOfPoints() + print 'nb_points =', nb_points + + nb_cells = mesh.GetNumberOfCells() + print 'nb_cells =', nb_cells + + return mesh diff --git a/vtk_py/readXMLUGrid.pyc b/vtk_py/readXMLUGrid.pyc new file mode 100644 index 0000000..128d68e Binary files /dev/null and b/vtk_py/readXMLUGrid.pyc differ diff --git a/vtk_py/rotatePData.py b/vtk_py/rotatePData.py new file mode 100644 index 0000000..a95f35e --- /dev/null +++ b/vtk_py/rotatePData.py @@ -0,0 +1,31 @@ +######################################################################## + +import numpy +import vtk + +######################################################################## + +def rotatePData(old_pdata, C, R, verbose=True): + if (verbose): print '*** rotatePData ***' + + nb_points = old_pdata.GetNumberOfPoints() + + new_points = vtk.vtkPoints() + new_points.SetNumberOfPoints(nb_points) + + old_point = numpy.array([0.]*3) + + for num_point in range(nb_points): + old_pdata.GetPoint(num_point, old_point) + #print old_point + + new_point = C + numpy.dot(R, old_point - C) + #print new_point + + new_points.InsertPoint(num_point, new_point) + + new_pdata = vtk.vtkPolyData() + new_pdata.SetPoints(new_points) + new_pdata.SetPolys(old_pdata.GetPolys()) + + return new_pdata diff --git a/vtk_py/rotatePData_w_axis.py b/vtk_py/rotatePData_w_axis.py new file mode 100644 index 0000000..3eeb2c9 --- /dev/null +++ b/vtk_py/rotatePData_w_axis.py @@ -0,0 +1,37 @@ +######################################################################## + +import numpy +import vtk +from pyquaternion import Quaternion + +######################################################################## + +def rotatePData_w_axis(old_pdata, angle, axis, verbose=True): + + if (verbose): print '*** rotatePData_w_axis ***' + + nb_points = old_pdata.GetNumberOfPoints() + + new_points = vtk.vtkPoints() + new_points.SetNumberOfPoints(nb_points) + + my_quaternion = Quaternion(axis=axis, angle=angle) + + old_point = numpy.array([0.]*3) + + for num_point in range(nb_points): + old_pdata.GetPoint(num_point, old_point) + #print old_point + + new_point = my_quaternion.rotate(old_point) + #print new_point + + new_points.InsertPoint(num_point, new_point) + + new_pdata = vtk.vtkPolyData() + new_pdata.SetPoints(new_points) + new_pdata.SetPolys(old_pdata.GetPolys()) + new_pdata.SetLines(old_pdata.GetLines()) + + return new_pdata + diff --git a/vtk_py/rotatePData_w_axis.pyc b/vtk_py/rotatePData_w_axis.pyc new file mode 100644 index 0000000..2e86c4e Binary files /dev/null and b/vtk_py/rotatePData_w_axis.pyc differ diff --git a/vtk_py/rotateSymmetricMatrix.py b/vtk_py/rotateSymmetricMatrix.py new file mode 100644 index 0000000..fd3f09f --- /dev/null +++ b/vtk_py/rotateSymmetricMatrix.py @@ -0,0 +1,78 @@ +######################################################################## + +import numpy +import vtk + +from mat_vec_tools import * +from createFloatArray import * + +######################################################################## + +def rotateSymmetricMatrix(old_array, in_vecs=None, out_vecs=None, verbose=True): + if (verbose): print '*** rotateSymmetricMatrix ***' + + nb_cells = old_array.GetNumberOfTuples() + new_array = createFloatArray("", 6, nb_cells) + + for num_cell in range(nb_cells): + old_matrix = vec_col_to_mat_sym(old_array.GetTuple(num_cell)) + + if (in_vecs == None): + in_R = numpy.eye(3) + else: + in_R = numpy.transpose(numpy.array([in_vecs[0].GetTuple(num_cell), + in_vecs[1].GetTuple(num_cell), + in_vecs[2].GetTuple(num_cell)])) + + if (out_vecs == None): + out_R = numpy.eye(3) + else: + out_R = numpy.transpose(numpy.array([out_vecs[0].GetTuple(num_cell), + out_vecs[1].GetTuple(num_cell), + out_vecs[2].GetTuple(num_cell)])) + + R = numpy.dot(numpy.transpose(in_R), out_R) + + new_matrix = numpy.dot(numpy.dot(numpy.transpose(R), old_matrix), R) + + new_array.InsertTuple(num_cell, mat_sym_to_vec_col(new_matrix)) + + return new_array + +#def rotateSymmetricMatrixToOrFromLocalCylindricalCoordinates(mesh, old_field_name, new_field_name, to_or_from, verbose=True): + #nb_cells = mesh.GetNumberOfCells() + + #old_field_array = mesh.GetCellData().GetArray(old_field_name) + + #eR_array = mesh.GetCellData().GetArray('eR') + #eC_array = mesh.GetCellData().GetArray('eC') + #eL_array = mesh.GetCellData().GetArray('eL') + + #if (verbose): print 'Rotating field and Filling mesh...' + + #new_field_array = vtk.vtkFloatArray() + #new_field_array.SetName(new_field_name) + #new_field_array.SetNumberOfComponents(6) + #new_field_array.SetNumberOfTuples(nb_cells) + + #for num_cell in range(nb_cells): + #old_matrix = vec_col_to_mat_sym(old_field_array.GetTuple(num_cell)) + + #eR = eR_array.GetTuple(num_cell) + #eC = eC_array.GetTuple(num_cell) + #eL = eL_array.GetTuple(num_cell) + + #R = numpy.transpose(numpy.array([eR, eC, eL])) + + #if (to_or_from == 'to'): new_matrix = numpy.dot(numpy.dot(numpy.transpose(R), old_matrix), R) + #elif (to_or_from == 'from'): new_matrix = numpy.dot(numpy.dot(R, old_matrix), numpy.transpose(R)) + + #new_field_array.InsertTuple(num_cell, mat_sym_to_vec_col(new_matrix)) + + #mesh.GetCellData().AddArray(new_field_array) + +#def rotateSymmetricMatrixToLocalCylindricalCoordinates(mesh, old_field_name, new_field_name, verbose=True): + #rotateSymmetricMatrixToOrFromLocalCylindricalCoordinates(mesh, old_field_name, new_field_name, 'to', verbose) + +#def rotateSymmetricMatrixFromLocalCylindricalCoordinates(mesh, old_field_name, new_field_name, verbose=True): + #rotateSymmetricMatrixToOrFromLocalCylindricalCoordinates(mesh, old_field_name, new_field_name, 'from', verbose) diff --git a/vtk_py/rotateSymmetricMatrix.pyc b/vtk_py/rotateSymmetricMatrix.pyc new file mode 100644 index 0000000..9e54676 Binary files /dev/null and b/vtk_py/rotateSymmetricMatrix.pyc differ diff --git a/vtk_py/rotateUGrid.py b/vtk_py/rotateUGrid.py new file mode 100644 index 0000000..c20ba72 --- /dev/null +++ b/vtk_py/rotateUGrid.py @@ -0,0 +1,30 @@ +######################################################################## + +import numpy +import vtk + +######################################################################## + +def rotateUGrid(ugrid, rx=0.0, ry=0.0, rz=0.0, sx=1.0, sy=1.0, sz=1.0, verbose=True): + + transmat = vtk.vtkTransform() + transmat.RotateX(rx) + transmat.RotateY(ry) + transmat.RotateZ(rz) + transmat.Scale(sx, sy, sz) + + transmat.Update() + + tf = vtk.vtkTransformFilter() + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + tf.SetInput(ugrid) + else: + tf.SetInputData(ugrid) + tf.SetTransform(transmat) + tf.Update() + + return tf.GetOutput() + + + + diff --git a/vtk_py/rotateUGrid.pyc b/vtk_py/rotateUGrid.pyc new file mode 100644 index 0000000..cf1a9c0 Binary files /dev/null and b/vtk_py/rotateUGrid.pyc differ diff --git a/vtk_py/sliceheart.py b/vtk_py/sliceheart.py new file mode 100644 index 0000000..8661af0 --- /dev/null +++ b/vtk_py/sliceheart.py @@ -0,0 +1,28 @@ +######################################################################## + +import sys +import vtk + +from mat_vec_tools import * + +######################################################################## + +def sliceheart(domain, C, N, verbose=True): + + if (verbose): print '*** Slice Heart ***' + + plane = vtk.vtkPlane() + plane.SetOrigin(C) + plane.SetNormal(N) + + cutter = vtk.vtkCutter() + cutter.SetCutFunction(plane) + if(vtk.vtkVersion().GetVTKMajorVersion() < 6): + cutter.SetInput(domain) + else: + cutter.SetInputData(domain) + cutter.Update() + + return cutter.GetOutput(); + + diff --git a/vtk_py/sliceheart.pyc b/vtk_py/sliceheart.pyc new file mode 100644 index 0000000..4aafdff Binary files /dev/null and b/vtk_py/sliceheart.pyc differ diff --git a/vtk_py/splitDomainBetweenEndoAndEpi.py b/vtk_py/splitDomainBetweenEndoAndEpi.py new file mode 100644 index 0000000..69316bb --- /dev/null +++ b/vtk_py/splitDomainBetweenEndoAndEpi.py @@ -0,0 +1,80 @@ +######################################################################## + +import sys +import vtk + +from mat_vec_tools import * + +######################################################################## + +def splitDomainBetweenEndoAndEpi(domain, verbose=True): + + if (verbose): print '*** splitDomainBetweenEndoAndEpi ***' + + connectivity0 = vtk.vtkConnectivityFilter() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + connectivity0.SetInputData(domain) + else: + connectivity0.SetInput(domain) + connectivity0.SetExtractionModeToSpecifiedRegions() + connectivity0.AddSpecifiedRegion(0) + connectivity0.Update() + ugrid0_temp = connectivity0.GetOutput() + + geom0 = vtk.vtkGeometryFilter() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + geom0.SetInputData(ugrid0_temp) + else: + geom0.SetInput(ugrid0_temp) + geom0.Update() + pdata0_temp = geom0.GetOutput() + + tfilter0 = vtk.vtkTriangleFilter() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + tfilter0.SetInputData(pdata0_temp) + else: + tfilter0.SetInput(pdata0_temp) + tfilter0.Update() + + connectivity1 = vtk.vtkConnectivityFilter() + connectivity1.SetExtractionModeToSpecifiedRegions() + connectivity1.AddSpecifiedRegion(1) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + connectivity1.SetInputData(domain) + else: + connectivity1.SetInput(domain) + connectivity1.Update() + ugrid1_temp = connectivity1.GetOutput() + geom1 = vtk.vtkGeometryFilter() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + geom1.SetInputData(ugrid1_temp) + else: + geom1.SetInput(ugrid1_temp) + geom1.Update() + pdata1_temp = geom1.GetOutput() + + + tfilter1 = vtk.vtkTriangleFilter() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + tfilter1.SetInputData(pdata1_temp) + else: + tfilter1.SetInput(pdata1_temp) + tfilter1.Update() + + pdata1 = tfilter1.GetOutput() + pdata0 = tfilter0.GetOutput() + + p0bd = pdata0.GetBounds() + p1bd = pdata1.GetBounds() + + if (abs(p1bd[0] - p1bd[1]) < abs(p0bd[0] - p0bd[1])): + pdata_epi = pdata0 + pdata_endo = pdata1 + else: + pdata_epi = pdata1 + pdata_endo = pdata0 + + return pdata_epi, pdata_endo + + + diff --git a/vtk_py/splitDomainBetweenEndoAndEpi.pyc b/vtk_py/splitDomainBetweenEndoAndEpi.pyc new file mode 100644 index 0000000..9b9dc98 Binary files /dev/null and b/vtk_py/splitDomainBetweenEndoAndEpi.pyc differ diff --git a/vtk_py/transform_mesh_w_4x4mat.py b/vtk_py/transform_mesh_w_4x4mat.py new file mode 100644 index 0000000..ba093cf --- /dev/null +++ b/vtk_py/transform_mesh_w_4x4mat.py @@ -0,0 +1,54 @@ +######################################################################## + +import sys +import numpy +import vtk +from vtk_py import * + +######################################################################## + +def transform_mesh_w_4x4mat(infilename, outfilename, matrix): + + ugrid = vtk.vtkUnstructuredGrid() + + if(infilename[len(infilename)-4:len(infilename)] == ".vtu"): + ugrid = readXMLUGrid(infilename) + elif(infilename[len(infilename)-4:len(infilename)] == ".vtk"): + ugrid = readUGrid(infilename) + + rot_mat = vtk.vtkMatrix4x4() + rot_mat.DeepCopy(matrix) + + transform = vtk.vtkTransform() + transform.SetMatrix(rot_mat) + transform.Update() + + transformfilter = vtk.vtkTransformFilter() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + transformfilter.SetInputData(ugrid) + else: + transformfilter.SetInput(ugrid) + transformfilter.SetTransform(transform) + transformfilter.Update() + + if(outfilename[len(outfilename)-4:len(outfilename)] == ".vtu"): + writeXMLUGrid(transformfilter.GetOutput(), outfilename) + elif(outfilename[len(outfilename)-4:len(outfilename)] == ".vtk"): + writeUGrid(transformfilter.GetOutput(), outfilename) + + + + +if (__name__ == "__main__"): + + print len(sys.argv) + assert (len(sys.argv) == 19), 'Number of arguments must be 3.' + infilename = sys.argv[1] + outfilename = sys.argv[2] + matrix = map(float,sys.argv[3:19]) + + print matrix + + transform_mesh_w_4x4mat(infilename, outfilename, matrix) + + diff --git a/vtk_py/transform_mesh_w_4x4mat.pyc b/vtk_py/transform_mesh_w_4x4mat.pyc new file mode 100644 index 0000000..fc4f2d6 Binary files /dev/null and b/vtk_py/transform_mesh_w_4x4mat.pyc differ diff --git a/vtk_py/transform_pdata.py b/vtk_py/transform_pdata.py new file mode 100644 index 0000000..8e72bd9 --- /dev/null +++ b/vtk_py/transform_pdata.py @@ -0,0 +1,32 @@ +######################################################################## + +import sys +import numpy +import vtk +from vtk_py import * + +######################################################################## + +def transform_pdata(pdata, transvec, rotatevec): + + transform = vtk.vtkTransform() + transform.Translate(transvec[0],transvec[1],transvec[2]) + transform.RotateX(rotatevec[0]) + transform.RotateY(rotatevec[1]) + transform.RotateZ(rotatevec[2]) + transform.Update() + + transformfilter = vtk.vtkTransformPolyDataFilter() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + transformfilter.SetInputData(pdata) + else: + transformfilter.SetInput(pdata) + transformfilter.SetTransform(transform) + transformfilter.Update() + + return transformfilter.GetOutput() + + + + + diff --git a/vtk_py/transform_pdata.pyc b/vtk_py/transform_pdata.pyc new file mode 100644 index 0000000..47a9da2 Binary files /dev/null and b/vtk_py/transform_pdata.pyc differ diff --git a/vtk_py/translate_mesh.py b/vtk_py/translate_mesh.py new file mode 100644 index 0000000..8751db0 --- /dev/null +++ b/vtk_py/translate_mesh.py @@ -0,0 +1,30 @@ +######################################################################## + +import sys +import numpy +import vtk +from vtk_py import * + +######################################################################## + +def translate_mesh(ugrid, vec): + + transform = vtk.vtkTransform() + transform.Translate(vec[0],vec[1],vec[2]) + transform.Update() + + transformfilter = vtk.vtkTransformFilter() + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + transformfilter.SetInputData(ugrid) + else: + transformfilter.SetInput(ugrid) + transformfilter.SetTransform(transform) + transformfilter.Update() + + return transformfilter.GetOutput() + + + + + + diff --git a/vtk_py/translate_mesh.pyc b/vtk_py/translate_mesh.pyc new file mode 100644 index 0000000..83b3989 Binary files /dev/null and b/vtk_py/translate_mesh.pyc differ diff --git a/vtk_py/vtkmtvfiber_sheet_vector_translator.py b/vtk_py/vtkmtvfiber_sheet_vector_translator.py new file mode 100644 index 0000000..e0415d8 --- /dev/null +++ b/vtk_py/vtkmtvfiber_sheet_vector_translator.py @@ -0,0 +1,263 @@ +######################################################################## + +import argparse +import glob +from numpy import * +from sets import Set +from vtk import * +import os + +import vtk_py as vtk_py + +######################################################################## + + + +parser = argparse.ArgumentParser() +parser.add_argument('--vtk_folder', type=str, required=True) +parser.add_argument('--vtk_filename', type=str, required=True) +parser.add_argument('--fiberdata_directory', type=str, required=True) +parser.add_argument('--mtv_grid_directory', type=str, required=True) +parser.add_argument('--mtv_basename', type=str, required=True) +args = parser.parse_args() + +print "************* Entering vtkmtvfiber_sheet_vector_translator.py *****************" + + +points = [] +fvectors = [] +svectors = [] + +srcfilename = os.path.join(args.vtk_folder, args.vtk_filename) +directory = args.fiberdata_directory +outdirectory = args.mtv_grid_directory +outfilename = args.mtv_basename + +reader = vtkUnstructuredGridReader(); +reader.SetFileName(srcfilename); +reader.Update(); + +mesh = vtkUnstructuredGrid(); +mesh.DeepCopy(reader.GetOutput()) + +rotate = 1; +bds = mesh.GetBounds() +zoffset = bds[5]; + + +rotate = 1; +# Import vtk file +# Read in LV fiber data +LVfiberreader = vtkXMLPolyDataReader(); +LVfiberreader.SetFileName(directory+"LVfiberdata.vtp"); +LVfiberreader.Update(); + +LVfiberdata = vtkPolyData(); +LVfiberdata.DeepCopy(LVfiberreader.GetOutput()) + +fvec = [0,0,0] +svec = [0,0,0] +pts = [0,0,0] +rotatedpt = [0,0,0] + +for p in range(0, LVfiberdata.GetPoints().GetNumberOfPoints()): + pt= LVfiberdata.GetPoints().GetPoint(p) + if(rotate == 0): + points.append(pt) + else: + rotatedpt[0] = float(-pt[2]+zoffset)/10.0; + rotatedpt[1] = float(pt[1])/10.0; + rotatedpt[2] = float(pt[0])/10.0; + points.append([rotatedpt[0], rotatedpt[1], rotatedpt[2]]) + + + LVfiberdata.GetPointData().SetActiveVectors("f vectors") + temp = LVfiberdata.GetPointData().GetVectors().GetTuple3(p); + fvec[0] = temp[0] + fvec[1] = temp[1] + fvec[2] = temp[2] + vtkMath.Normalize(fvec) + if(rotate == 0): + fvectors.append([fvec[0], fvec[1], fvec[2]]) + else: + fvectors.append([-1.0*fvec[2], fvec[1], fvec[0]]) + + + LVfiberdata.GetPointData().SetActiveVectors("n vectors") + temp = LVfiberdata.GetPointData().GetVectors().GetTuple3(p); + svec[0] = temp[0] + svec[1] = temp[1] + svec[2] = temp[2] + vtkMath.Normalize(svec) + if(rotate == 0): + svectors.append([svec[0], svec[1], svec[2]]) + else: + svectors.append([-1.0*svec[2], svec[1], svec[0]]) + + +# Read in RV fiber data +RVfiberreader = vtkXMLPolyDataReader(); +RVfiberreader.SetFileName(directory+"RVfiberdata.vtp"); +RVfiberreader.Update(); + +RVfiberdata = vtkPolyData(); +RVfiberdata.DeepCopy(RVfiberreader.GetOutput()) + +fvec = [0,0,0] +svec = [0,0,0] +pts = [0,0,0] + +rotatedpt = [0,0,0] + +for p in range(0, RVfiberdata.GetPoints().GetNumberOfPoints()): + pt= RVfiberdata.GetPoints().GetPoint(p) + if(rotate == 0): + points.append(pt) + else: + rotatedpt[0] = float(-pt[2]+zoffset)/10.0; + rotatedpt[1] = float(pt[1])/10.0; + rotatedpt[2] = float(pt[0])/10.0; + points.append([rotatedpt[0], rotatedpt[1], rotatedpt[2]]) + + + + RVfiberdata.GetPointData().SetActiveVectors("f vectors") + temp = RVfiberdata.GetPointData().GetVectors().GetTuple3(p); + fvec[0] = temp[0] + fvec[1] = temp[1] + fvec[2] = temp[2] + vtkMath.Normalize(fvec) + if(rotate == 0): + fvectors.append([fvec[0], fvec[1], fvec[2]]) + else: + fvectors.append([-1.0*fvec[2], fvec[1], fvec[0]]) + + RVfiberdata.GetPointData().SetActiveVectors("n vectors") + temp = RVfiberdata.GetPointData().GetVectors().GetTuple3(p); + svec[0] = temp[0] + svec[1] = temp[1] + svec[2] = temp[2] + vtkMath.Normalize(svec) + if(rotate == 0): + svectors.append([svec[0], svec[1], svec[2]]) + else: + svectors.append([-1.0*svec[2], svec[1], svec[0]]) + + + +# Read in Septum fiber data +Septumfiberreader = vtkXMLPolyDataReader(); +Septumfiberreader.SetFileName(directory+"Septumfiberdata.vtp"); +Septumfiberreader.Update(); + +Septumfiberdata = vtkPolyData(); +Septumfiberdata.DeepCopy(Septumfiberreader.GetOutput()) + +fvec = [0,0,0] +svec = [0,0,0] +pts = [0,0,0] +rotatedpt = [0,0,0] + + +for p in range(0, Septumfiberdata.GetPoints().GetNumberOfPoints()): + pt= Septumfiberdata.GetPoints().GetPoint(p) + if(rotate == 0): + points.append(pt) + else: + rotatedpt[0] = float(-pt[2]+zoffset)/10.0; + rotatedpt[1] = float(pt[1])/10.0; + rotatedpt[2] = float(pt[0])/10.0; + points.append([rotatedpt[0], rotatedpt[1], rotatedpt[2]]) + + + Septumfiberdata.GetPointData().SetActiveVectors("f vectors") + temp = Septumfiberdata.GetPointData().GetVectors().GetTuple3(p); + fvec[0] = temp[0] + fvec[1] = temp[1] + fvec[2] = temp[2] + vtkMath.Normalize(fvec) + if(rotate == 0): + fvectors.append([fvec[0], fvec[1], fvec[2]]) + else: + fvectors.append([-1.0*fvec[2], fvec[1], fvec[0]]) + + + Septumfiberdata.GetPointData().SetActiveVectors("n vectors") + temp = Septumfiberdata.GetPointData().GetVectors().GetTuple3(p); + svec[0] = temp[0] + svec[1] = temp[1] + svec[2] = temp[2] + vtkMath.Normalize(svec) + if(rotate == 0): + svectors.append([svec[0], svec[1], svec[2]]) + else: + svectors.append([-1.0*svec[2], svec[1], svec[0]]) + + +mtvfiberfilename = outdirectory+outfilename+"_fiber_rotated.axis" +mtvfiberfile = open(mtvfiberfilename, 'w') +print >>mtvfiberfile, len(fvectors), 10 + +mtvsheetfilename = outdirectory+outfilename+"_sheet_rotated.axis" +mtvsheetfile = open(mtvsheetfilename, 'w') +print >>mtvsheetfile, len(svectors) + +pdata = vtk.vtkPolyData() +ppoints = vtk.vtkPoints() +cellarray = vtk.vtkCellArray() + +fvector = vtk.vtkFloatArray() +fvector.SetNumberOfComponents(3) +fvector.SetName("f vectors") +svector = vtk.vtkFloatArray() +svector.SetNumberOfComponents(3) +svector.SetName("s vectors") +nvector = vtk.vtkFloatArray() +nvector.SetNumberOfComponents(3) +nvector.SetName("n vectors") + +for p in range(0,len(fvectors)): + + print >>mtvfiberfile, points[p][0], points[p][1], points[p][2], fvectors[p][0], fvectors[p][1], fvectors[p][2] + print >>mtvsheetfile, points[p][0], points[p][1], points[p][2], svectors[p][0], svectors[p][1], svectors[p][2] + + ppoints.InsertNextPoint(points[p][0],points[p][1], points[p][2]) + + vert = vtk.vtkVertex() + vert.GetPointIds().SetId(0,p) + cellarray.InsertNextCell(vert) + + fvector.InsertNextTuple3(fvectors[p][0], fvectors[p][1], fvectors[p][2]) + svector.InsertNextTuple3(svectors[p][0], svectors[p][1], svectors[p][2]) + + f = array([fvectors[p][0], fvectors[p][1], fvectors[p][2]]) + s = array([svectors[p][0], svectors[p][1], svectors[p][2]]) + n = cross(f,s) + + nvector.InsertNextTuple3(n[0], n[1], n[2]) + +pdata.SetPoints(ppoints) +pdata.SetVerts(cellarray) +pdata.GetPointData().SetActiveVectors("f vectors") +pdata.GetPointData().SetVectors(fvector) +pdata.GetPointData().SetActiveVectors("s vectors") +pdata.GetPointData().SetVectors(svector) +pdata.GetPointData().SetActiveVectors("n vectors") +pdata.GetPointData().SetVectors(nvector) + + +newfilename = outdirectory + outfilename + "_scaled_rotated.vtp" + +writer = vtk.vtkXMLPolyDataWriter() +writer.SetFileName(newfilename) +if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + writer.SetInput(pdata) +else: + writer.SetInputData(pdata) +writer.Write() + +mtvfiberfile.close() +mtvsheetfile.close() + + +print "************* Leaving vtkmtvfiber_sheet_vector_translator.py *****************" diff --git a/vtk_py/vtkmtvfiber_sheet_vector_translator_LVonly.py b/vtk_py/vtkmtvfiber_sheet_vector_translator_LVonly.py new file mode 100644 index 0000000..a4ca733 --- /dev/null +++ b/vtk_py/vtkmtvfiber_sheet_vector_translator_LVonly.py @@ -0,0 +1,162 @@ +######################################################################## + +import argparse +import glob +from numpy import * +from sets import Set +from vtk import * +import os + +import vtk_py as vtk_py + +######################################################################## + +def transform_scale_n_write(mesh, outdirectory): + + newfilename = outdirectory + "fiberdata" +"_scaled_rotated.vtp" + + bds = mesh.GetBounds() + + trans = vtk.vtkTransform() + trans.Translate(bds[5]/10,0,0) + trans.RotateY(-90) + trans.Scale(0.1, 0.1, 0.1) + + transfilter = vtk.vtkTransformPolyDataFilter() + transfilter.SetTransform(trans) + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + transfilter.SetInput(mesh) + else: + transfilter.SetInputData(mesh) + transfilter.Update() + + writer = vtk.vtkXMLPolyDataWriter() + writer.SetFileName(newfilename) + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + writer.SetInput(transfilter.GetOutput()) + else: + writer.SetInputData(transfilter.GetOutput()) + writer.Write() + +parser = argparse.ArgumentParser() +parser.add_argument('--vtk_folder', type=str, required=True) +parser.add_argument('--vtk_filename', type=str, required=True) +parser.add_argument('--fiberdata_directory', type=str, required=True) +parser.add_argument('--mtv_grid_directory', type=str, required=True) +parser.add_argument('--mtv_basename', type=str, required=True) +parser.add_argument('--scale', type=float, required=True) +args = parser.parse_args() + +print "************* Entering vtkmtvfiber_sheet_vector_translator_LVonly.py *****************" + + +points = [] +fvectors = [] +svectors = [] + +srcfilename = os.path.join(args.vtk_folder, args.vtk_filename) +directory = args.fiberdata_directory +outdirectory = args.mtv_grid_directory +outfilename = args.mtv_basename +scale = args.scale + +#srcfilename = "/home/likchuan/Research/C++/heartmech_bitbucket/pulse_cmake/pulse-cmake-growth/cases/singleLV/mesh/LV_fine.vtu" +#directory = "/home/likchuan/Research/C++/heartmech_bitbucket/pulse_cmake/pulse-cmake-growth/cases/singleLV/mesh/" +#outdirectory = "/home/likchuan/Research/C++/heartmech_bitbucket/pulse_cmake/pulse-cmake-growth/cases/singleLV/mesh/" +#outfilename = "LV_fiber_fine" + +reader = vtkXMLUnstructuredGridReader(); +reader.SetFileName(srcfilename); +reader.Update(); + + +mesh = vtkUnstructuredGrid(); +mesh.DeepCopy(reader.GetOutput()) + +rotate = 1; +bds = mesh.GetBounds() +zoffset = bds[5]; + + +rotate = 1; +# Import vtk file +# Read in LV fiber data +LVfiberreader = vtkXMLPolyDataReader(); +LVfiberreader.SetFileName(directory+"fiberdirections.vtp"); +LVfiberreader.Update(); + +LVfiberdata = vtkPolyData(); +LVfiberdata.DeepCopy(LVfiberreader.GetOutput()) + +fvec = [0,0,0] +svec = [0,0,0] +pts = [0,0,0] +rotatedpt = [0,0,0] + +for p in range(0, LVfiberdata.GetPoints().GetNumberOfPoints()): + pt= LVfiberdata.GetPoints().GetPoint(p) + if(rotate == 0): + points.append(pt) + else: + rotatedpt[0] = float(-pt[2]+zoffset)/scale; + rotatedpt[1] = float(pt[1])/scale; + rotatedpt[2] = float(pt[0])/scale; + #print rotatedpt + points.append([rotatedpt[0], rotatedpt[1], rotatedpt[2]]) + + + LVfiberdata.GetPointData().SetActiveVectors("fiber vectors") + temp = LVfiberdata.GetPointData().GetVectors().GetTuple3(p); + fvec[0] = temp[0] + fvec[1] = temp[1] + fvec[2] = temp[2] + vtkMath.Normalize(fvec) + if(rotate == 0): + fvectors.append([fvec[0], fvec[1], fvec[2]]) + else: + fvectors.append([-1.0*fvec[2], fvec[1], fvec[0]]) + + + LVfiberdata.GetPointData().SetActiveVectors("sheet vectors") + temp = LVfiberdata.GetPointData().GetVectors().GetTuple3(p); + svec[0] = temp[0] + svec[1] = temp[1] + svec[2] = temp[2] + vtkMath.Normalize(svec) + if(rotate == 0): + svectors.append([svec[0], svec[1], svec[2]]) + else: + svectors.append([-1.0*svec[2], svec[1], svec[0]]) + + +# Appending PolyData +appendeddata = vtk.vtkAppendPolyData() +if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + appendeddata.AddInput(LVfiberreader.GetOutput()) +else: + appendeddata.AddInputData(LVfiberreader.GetOutput()) +appendeddata.Update() + +#print appendeddata.GetOutput() + +#transform_scale_n_write(appendeddata.GetOutput(), outdirectory) + + +mtvfiberfilename = outdirectory+outfilename+"_fiber_rotated.axis" +mtvfiberfile = open(mtvfiberfilename, 'w') +print >>mtvfiberfile, len(fvectors), 10 + +mtvsheetfilename = outdirectory+outfilename+"_sheet_rotated.axis" +mtvsheetfile = open(mtvsheetfilename, 'w') +print >>mtvsheetfile, len(svectors) + +for p in range(0,len(fvectors)): + print >>mtvfiberfile, points[p][0], points[p][1], points[p][2], fvectors[p][0], fvectors[p][1], fvectors[p][2] + print >>mtvsheetfile, points[p][0], points[p][1], points[p][2], svectors[p][0], svectors[p][1], svectors[p][2] + + +mtvfiberfile.close() +mtvsheetfile.close() + + +print "************* Leaving vtkmtvfiber_sheet_vector_translator.py *****************" diff --git a/vtk_py/vtkmtvtranslator_lintets_LVonly_v1.py b/vtk_py/vtkmtvtranslator_lintets_LVonly_v1.py new file mode 100644 index 0000000..1d22c86 --- /dev/null +++ b/vtk_py/vtkmtvtranslator_lintets_LVonly_v1.py @@ -0,0 +1,462 @@ +######################################################################## + +import argparse +import glob +from numpy import * +from sets import Set +from vtk import * +import os + +import vtk_py as vtk_py + +######################################################################## + + + +def extract_tetra(mesh): + + idlist = vtk.vtkIdList() + celltype = mesh.GetCellTypesArray() + for p in range(0, celltype.GetNumberOfTuples()): + if(float(celltype.GetTuple(p)[0]) == 10): + idlist.InsertNextId(p) + + extracted = vtk.vtkExtractCells() + extracted.SetCellList(idlist) + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + extracted.SetInput(mesh) + else: + extracted.SetInputData(mesh) + extracted.Update() + + return extracted.GetOutput() + + + +def writepdata(filename, pdata): + + pdatawriter = vtk.vtkXMLPolyDataWriter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + pdatawriter.SetInput(pdata) + else: + pdatawriter.SetInputData(pdata) + pdatawriter.SetFileName(filename) + pdatawriter.Write() + + + +def savepoints(ugrid, nodeids, ptfilename): + + # View points + viewpts = vtk.vtkPoints() + viewptspdata =vtk.vtkPolyData() + for p in range(0, nodeids.GetNumberOfIds()): + pt = [0,0,0] + pt = ugrid.GetPoints().GetPoint(nodeids.GetId(p)) + viewpts.InsertNextPoint(pt) + + viewptspdata.SetPoints(viewpts) + + maskPoints = vtk.vtkMaskPoints() + maskPoints.SetOnRatio(1); + maskPoints.SetInput(viewptspdata); + maskPoints.GenerateVerticesOn(); + maskPoints.Update(); + + writepdata(ptfilename, maskPoints.GetOutput()) + + +def extract_LV_surf_nodes(ugrid): + + Basalsurfnodes = vtk.vtkIdList() + Episurfnodes = vtk.vtkIdList() + LVEndosurfnodes = vtk.vtkIdList() + Basalepisurfnodes = vtk.vtkIdList() + + Episurf = vtk.vtkPolyData() + LVEndosurf = vtk.vtkPolyData() + + Idfilter = vtk.vtkIdFilter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + Idfilter.SetInput(ugrid) + else: + Idfilter.SetInputData(ugrid) + Idfilter.Update() + + geomfilter = vtk.vtkGeometryFilter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + geomfilter.SetInput(Idfilter.GetOutput()) + else: + geomfilter.SetInputData(Idfilter.GetOutput()) + geomfilter.Update() + + cleanpdata = vtk.vtkCleanPolyData() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + cleanpdata.SetInput(geomfilter.GetOutput()) + else: + cleanpdata.SetInputData(geomfilter.GetOutput()) + cleanpdata.Update() + + pdatanormal = vtk.vtkPolyDataNormals() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + pdatanormal.SetInput(cleanpdata.GetOutput()) + else: + pdatanormal.SetInputData(cleanpdata.GetOutput()) + pdatanormal.ComputeCellNormalsOn() + pdatanormal.Update() + + reducedsurfacemesh = vtk.vtkPolyData() + reducedsurfacemesh.DeepCopy(pdatanormal.GetOutput()) + reducedsurfacemesh.BuildLinks() + + bds = reducedsurfacemesh.GetBounds() + numcells = reducedsurfacemesh.GetNumberOfCells() + tol = 1e-1; + for p in range(0, numcells): + + ptlist = vtk.vtkIdList() + normvec = reducedsurfacemesh.GetCellData().GetArray("Normals").GetTuple3(p) + + # If cell normal is in 0,0,1 direction + if(abs(vtkMath.Dot(normvec, [1,0,0])) < tol and abs(vtkMath.Dot(normvec, [0,1,0])) < tol): + reducedsurfacemesh.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = reducedsurfacemesh.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + + pt = [0,0,0] + pt = ugrid.GetPoints().GetPoint(ptid) + + if(pt[2] > 0.5*(bds[5] + bds[4])): + Basalsurfnodes.InsertUniqueId(ptid) + + reducedsurfacemesh.DeleteCell(p) + + reducedsurfacemesh.RemoveDeletedCells(); + #reducedsurfacemesh.Update() + + + # Split the surfaces to LVendo, RVendo, Epi + connectivityfilter = vtk.vtkPolyDataConnectivityFilter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + connectivityfilter.SetInput(reducedsurfacemesh) + else: + connectivityfilter.SetInputData(reducedsurfacemesh) + connectivityfilter.Update() + + # Extracting Epi surface + connectivityfilter.SetExtractionModeToLargestRegion(); + connectivityfilter.ColorRegionsOn(); + connectivityfilter.Update(); + Episurf.DeepCopy(connectivityfilter.GetOutput()); + + zrange = [] + for p in range(0, 3): + + connectivityfilter.AddSpecifiedRegion(p); + connectivityfilter.SetExtractionModeToSpecifiedRegions(); + connectivityfilter.Update(); + connectivityfilter.DeleteSpecifiedRegion(p); + + bds = connectivityfilter.GetOutput().GetBounds() + zrange.append(abs(bds[5] - bds[4])) + + epiids = zrange.index(max(zrange)) + RVendoids = zrange.index(min(zrange)) + idlist = set([0,1]) + #LVendoids = list(idlist.difference(set([epiids, RVendoids])))[0] + LVendoids = list(idlist.difference(set([epiids])))[0] + + # Extracting LV surface + connectivityfilter.AddSpecifiedRegion(LVendoids); + connectivityfilter.SetExtractionModeToSpecifiedRegions(); + connectivityfilter.Update(); + LVEndosurf.DeepCopy(connectivityfilter.GetOutput()); + connectivityfilter.DeleteSpecifiedRegion(LVendoids); + + # Get Epi surface points + for p in range(0, Episurf.GetNumberOfCells()): + ptlist = vtk.vtkIdList() + Episurf.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = Episurf.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + Episurfnodes.InsertUniqueId(ptid) + + + # Get LV surface points + for p in range(0, LVEndosurf.GetNumberOfCells()): + ptlist = vtk.vtkIdList() + LVEndosurf.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = LVEndosurf.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + LVEndosurfnodes.InsertUniqueId(ptid) + + # Get Epi basal edge points + Basalepisurfnodes.DeepCopy(Basalsurfnodes) + Basalepisurfnodes.IntersectWith(Episurfnodes) + + + return Basalsurfnodes, Basalepisurfnodes, Episurfnodes, LVEndosurfnodes + + + +def set_pix_intensity(mesh, vtuoutputdir, vtufilename, txtoutputdir, txtfilename): + + + outvtufilename = vtuoutputdir + vtufilename + outtxtfilename = txtoutputdir + txtfilename + + txtfile = open(outtxtfilename, "w"); + + cellpixintensity = mesh.GetCellData().GetScalars("closest_pix_intensity") + print cellpixintensity.GetNumberOfTuples() + + rangeofpixintensity = cellpixintensity.GetValueRange() + + + matid = vtk.vtkIntArray() + matid.SetNumberOfComponents(1) + matid.SetName("Material Id") + + normalized_pix = vtk.vtkFloatArray() + normalized_pix.SetNumberOfComponents(1) + normalized_pix.SetName("Normalized Pixel Intensity") + + for p in range(0, mesh.GetNumberOfCells()): + + pix_intensity = cellpixintensity.GetTuple(p) + normalized_pix_intensity = (pix_intensity[0] - rangeofpixintensity[0])/(rangeofpixintensity[1] - rangeofpixintensity[0]) + + normalized_pix.InsertNextValue(normalized_pix_intensity) + + print >>txtfile, p+1, normalized_pix_intensity + + txtfile.close() + + #mesh.GetCellData().SetActiveScalars("Material Id") + #mesh.GetCellData().SetScalars(matid) + + mesh.GetCellData().SetActiveScalars("Normalized_Pixel_Intensity") + mesh.GetCellData().SetScalars(normalized_pix) + + writer = vtk.vtkXMLUnstructuredGridWriter() + writer.SetFileName(outvtufilename) + writer.SetInput(mesh) + writer.Write(); + +def transform_scale_n_write(mesh, outdirectory, vtufilename): + + newfilename = outdirectory + vtufilename[0:len(vtufilename)-4]+"_scaled_rotated.vtu" + + + bds = mesh.GetBounds() + + trans = vtk.vtkTransform() + trans.Translate(bds[5]/10,0,0) + trans.RotateY(-90) + trans.Scale(0.1, 0.1, 0.1) + + + transfilter = vtk.vtkTransformFilter() + transfilter.SetTransform(trans) + transfilter.SetInput(mesh) + + writer = vtk.vtkXMLUnstructuredGridWriter() + writer.SetFileName(newfilename) + writer.SetInput(transfilter.GetOutput()) + writer.Write() + +def convert_lintets_2_mtv(mesh, outdirectory, name, issavepts, isrotate, basalnormal, tol, epispringcond, scale): + + + rotate = isrotate; + bds = mesh.GetBounds() + if(basalnormal == 'z'): + zoffset = bds[5]; + print "z offset = ", zoffset + elif(basalnormal == 'x'): + zoffset = bds[1]; + print "x offset = ", zoffset + + filename = outdirectory + name + ".grid" + mtvfile = open(filename, 'w') + + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, "Finite element mesh (MLGridFEAdB)" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, "Finite element mesh (GridFE):" + print >>mtvfile, " " + print >>mtvfile, " Number of space dim. = 3 embedded in physical space with dimension 3" + print >>mtvfile, " Number of elements = %5d" %mesh.GetNumberOfCells() + print >>mtvfile, " Number of nodes = %5d" %mesh.GetNumberOfPoints() + print >>mtvfile, " " + print >>mtvfile, " All elements are of the same type : true" + print >>mtvfile, " Max number of nodes in an element: 4" + print >>mtvfile, " Only one material : false" + print >>mtvfile, " Lattice data ? 0" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " 12 boundary indicators: " + print >>mtvfile, " P1" + print >>mtvfile, " P2" + print >>mtvfile, " P3" + print >>mtvfile, " T1" + print >>mtvfile, " T2" + print >>mtvfile, " u1=0" + print >>mtvfile, " u2=0" + print >>mtvfile, " u3=0" + print >>mtvfile, " u1=u1_0" + print >>mtvfile, " u2=u2_0" + print >>mtvfile, " u3=u3_0" + print >>mtvfile, " free" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " Nodal coordinates and nodal boundary indicators," + print >>mtvfile, " the columns contain:" + print >>mtvfile, " - node number" + print >>mtvfile, " - coordinates" + print >>mtvfile, " - no of boundary indicators that are set (ON)" + print >>mtvfile, " - the boundary indicators that are set (ON) if any." + print >>mtvfile, "#" + + + # Get Surface nodes for pressure constraint + Basalsurfnodes, Basalepisurfnodes, Episurfnodes, LVEndosurfnodes = extract_LV_surf_nodes(mesh) + + if(issavepts == 1): + ptfilename = outdirectory + name + '_Basalsurfnodes.vtp' + savepoints(mesh, Basalsurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_Basalepisurfnodes.vtp' + savepoints(mesh, Basalepisurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_Episurfnodes.vtp' + savepoints(mesh, Episurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_LVEndosurfnodes.vtp' + savepoints(mesh, LVEndosurfnodes, ptfilename) + + + + num_bindicator = zeros(mesh.GetNumberOfPoints()); + bindicator = ['']*mesh.GetNumberOfPoints(); + + for k in range(0,Episurfnodes.GetNumberOfIds()): + nodeid = Episurfnodes.GetId(k) + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + if(epispringcond): + bindicator[nodeid] = bindicator[nodeid] + ' 4' + else: + bindicator[nodeid] = bindicator[nodeid] + ' 3' + + for k in range(0,LVEndosurfnodes.GetNumberOfIds()): + nodeid = LVEndosurfnodes.GetId(k) + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 1' + + for k in range(0,Basalepisurfnodes.GetNumberOfIds()): + nodeid = Basalepisurfnodes.GetId(k) + if(epispringcond): + num_bindicator[nodeid] = num_bindicator[nodeid] + 0 + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 3 + bindicator[nodeid] = bindicator[nodeid] + ' 6 7 8' + + for k in range(0,Basalsurfnodes.GetNumberOfIds()): + nodeid = Basalsurfnodes.GetId(k) + if(rotate == 0): + if(Basalepisurfnodes.IsId(nodeid) == -1): + if(epispringcond): + num_bindicator[nodeid] = num_bindicator[nodeid] + 0 + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 8' + else: + if(Basalepisurfnodes.IsId(nodeid) == -1): + if(epispringcond): + num_bindicator[nodeid] = num_bindicator[nodeid] + 0 + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 6' + + + #print bindicator + pt = [0,0,0]; + rotatedpt = [0,0,0]; + #num_bindicator = 0; + #bindicator = " "; + for p in range(0, mesh.GetNumberOfPoints()): + if(rotate == 0): + mesh.GetPoints().GetPoint(p,pt); + print >>mtvfile, "%6d ( %11.5e, %11.5e, %11.5e) [%d] %s " %((p+1), pt[0], pt[1], pt[2], num_bindicator[p], bindicator[p] ) + else: + mesh.GetPoints().GetPoint(p,pt); + rotatedpt[0] = (-pt[2]+zoffset)/1.0; + rotatedpt[1] = (pt[1])/1.0; + rotatedpt[2] = (pt[0])/1.0; + + print >>mtvfile, "%6d ( %11.5e, %11.5e, %11.5e) [%d] %s " %((p+1), rotatedpt[0], rotatedpt[1], rotatedpt[2], num_bindicator[p], bindicator[p] ) + + print >>mtvfile, " " + print >>mtvfile, " Element types and connectivity" + print >>mtvfile, " the columns contain:" + print >>mtvfile, " - element number" + print >>mtvfile, " - element type" + print >>mtvfile, " - material number" + print >>mtvfile, " - the global node numbers of the nodes in the element." + print >>mtvfile, "#" + + + materialid = mesh.GetCellData().GetArray('Material Id') + ptid = vtkIdList() + ids = [0,0,0,0,0,0,0,0,0,0]; + + for p in range(0, mesh.GetNumberOfCells()): + mesh.GetCellPoints(p, ptid); + for j in range(0, 4): + ids[j] = int(ptid.GetId(j)); + try: + matid = materialid.GetValue(p) + + except AttributeError: + matid = 1 + + print >>mtvfile, "%5d ElmT4n3D %1d %5d %5d %5d %5d " %((p+1), matid, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1) + + + mtvfile.close() + + +tol = 1e-1 +parser = argparse.ArgumentParser() +parser.add_argument('--vtk_folder', type=str, required=True) +parser.add_argument('--vtk_filename', type=str, required=True) +parser.add_argument('--mtv_grid_directory', type=str, required=True) +parser.add_argument('--mtv_basename', type=str, required=True) +parser.add_argument('--isepispring', type=int, required=True) +parser.add_argument('--scale', type=float, required=True) +args = parser.parse_args() + + +print "************* Entering vtkmtvtranslator_lintets_v1.py *****************" + +if(args.isepispring): + print "Enforce spring B.C on epi" + + +if (args.vtk_filename[len(args.vtk_filename)-3:len(args.vtk_filename)] == 'vtu'): + print os.path.join(args.vtk_folder, args.vtk_filename) + mesh = vtk_py.readXMLUGrid(os.path.join(args.vtk_folder, args.vtk_filename)) +else: + mesh = vtk_py.readUGrid(os.path.join(args.vtk_folder, args.vtk_filename)) + +mesh = extract_tetra(mesh) + +convert_lintets_2_mtv(mesh, args.mtv_grid_directory, args.mtv_basename, 1, 1, "z", tol, args.isepispring, args.scale) + +print "************* Leaving vtkmtvtranslator_lintets_v1.py *****************" + + diff --git a/vtk_py/vtkmtvtranslator_lintets_v1.py b/vtk_py/vtkmtvtranslator_lintets_v1.py new file mode 100644 index 0000000..c3ca94d --- /dev/null +++ b/vtk_py/vtkmtvtranslator_lintets_v1.py @@ -0,0 +1,554 @@ +######################################################################## + +import argparse +import glob +from numpy import * +from sets import Set +from vtk import * +import os + +import vtk_py as vtk_py + +######################################################################## + + + + +def extract_tetra(mesh): + + idlist = vtk.vtkIdList() + celltype = mesh.GetCellTypesArray() + for p in range(0, celltype.GetNumberOfTuples()): + if(float(celltype.GetTuple(p)[0]) == 10): + idlist.InsertNextId(p) + + extracted = vtk.vtkExtractCells() + extracted.SetCellList(idlist) + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + extracted.SetInput(mesh) + else: + extracted.SetInputData(mesh) + extracted.Update() + + return extracted.GetOutput() + + + +def writepdata(filename, pdata): + + pdatawriter = vtk.vtkXMLPolyDataWriter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + pdatawriter.SetInput(pdata) + else: + pdatawriter.SetInputData(pdata) + pdatawriter.SetFileName(filename) + pdatawriter.Write() + + + +def savepoints(ugrid, nodeids, ptfilename): + + # View points + viewpts = vtk.vtkPoints() + viewptspdata =vtk.vtkPolyData() + for p in range(0, nodeids.GetNumberOfIds()): + pt = [0,0,0] + pt = ugrid.GetPoints().GetPoint(nodeids.GetId(p)) + viewpts.InsertNextPoint(pt) + + viewptspdata.SetPoints(viewpts) + + maskPoints = vtk.vtkMaskPoints() + maskPoints.SetOnRatio(1); + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + maskPoints.SetInput(viewptspdata); + else: + maskPoints.SetInputData(viewptspdata); + maskPoints.GenerateVerticesOn(); + maskPoints.Update(); + + writepdata(ptfilename, maskPoints.GetOutput()) + + +def extract_biven_surf_nodes(ugrid, basalnormal, tol): + + Basalsurfnodes = vtk.vtkIdList() + Episurfnodes = vtk.vtkIdList() + RVEndosurfnodes = vtk.vtkIdList() + LVEndosurfnodes = vtk.vtkIdList() + Basalepisurfnodes = vtk.vtkIdList() + + Episurf = vtk.vtkPolyData() + LVEndosurf = vtk.vtkPolyData() + RVEndosurf = vtk.vtkPolyData() + + Idfilter = vtk.vtkIdFilter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + Idfilter.SetInput(ugrid) + else: + Idfilter.SetInputData(ugrid) + Idfilter.Update() + + geomfilter = vtk.vtkGeometryFilter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + geomfilter.SetInput(Idfilter.GetOutput()) + else: + geomfilter.SetInputData(Idfilter.GetOutput()) + geomfilter.Update() + + cleanpdata = vtk.vtkCleanPolyData() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + cleanpdata.SetInput(geomfilter.GetOutput()) + else: + cleanpdata.SetInputData(geomfilter.GetOutput()) + cleanpdata.Update() + + pdatanormal = vtk.vtkPolyDataNormals() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + pdatanormal.SetInput(cleanpdata.GetOutput()) + else: + pdatanormal.SetInputData(cleanpdata.GetOutput()) + pdatanormal.ComputeCellNormalsOn() + pdatanormal.Update() + + #vtk_py.writeXMLPData(pdatanormal.GetOutput(), "test.vtp") + + reducedsurfacemesh = vtk.vtkPolyData() + reducedsurfacemesh.DeepCopy(pdatanormal.GetOutput()) + reducedsurfacemesh.BuildLinks() + + bds = reducedsurfacemesh.GetBounds() + numcells = reducedsurfacemesh.GetNumberOfCells() + for p in range(0, numcells): + + ptlist = vtk.vtkIdList() + normvec = reducedsurfacemesh.GetCellData().GetArray("Normals").GetTuple3(p) + + # If cell normal is in 0,0,1 direction + if(basalnormal == 'z'): + if(abs(vtkMath.Dot(normvec, [1,0,0])) < tol and abs(vtkMath.Dot(normvec, [0,1,0])) < tol): + reducedsurfacemesh.GetCellPoints(p, ptlist) + count_nodes_at_base = 0; + for j in range(0, ptlist.GetNumberOfIds()): + ptid = reducedsurfacemesh.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + + pt = [0,0,0] + pt = ugrid.GetPoints().GetPoint(ptid) + + if(pt[2] > 0.5*(bds[5] + bds[4])): + Basalsurfnodes.InsertUniqueId(ptid) + + if(pt[2] > bds[5] - tol): + count_nodes_at_base = count_nodes_at_base + 1 + + if(count_nodes_at_base == 3): + reducedsurfacemesh.DeleteCell(p) + + elif(basalnormal =='x'): + + if(abs(vtkMath.Dot(normvec, [0,0,1])) < tol and abs(vtkMath.Dot(normvec, [0,1,0])) < tol): + reducedsurfacemesh.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = reducedsurfacemesh.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + + pt = [0,0,0] + pt = ugrid.GetPoints().GetPoint(ptid) + + + if(pt[0] < bds[0] + tol): + Basalsurfnodes.InsertUniqueId(ptid) + + if(pt[0] < bds[0] + tol): + reducedsurfacemesh.DeleteCell(p) + + + + reducedsurfacemesh.RemoveDeletedCells(); + #reducedsurfacemesh.Update() + + + # Split the surfaces to LVendo, RVendo, Epi + connectivityfilter = vtk.vtkPolyDataConnectivityFilter() + connectivityfilter.SetScalarConnectivity(0); + connectivityfilter.ColorRegionsOn(); + connectivityfilter.SetExtractionModeToAllRegions() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + connectivityfilter.SetInput(reducedsurfacemesh) + else: + connectivityfilter.SetInputData(reducedsurfacemesh) + connectivityfilter.Update() + + print "Number of connected regions = ", connectivityfilter.GetNumberOfExtractedRegions() + vtk_py.writeXMLPData(connectivityfilter.GetOutput(), "connectedregion.vtp") + + + # Extracting Epi surface + connectivityfilter.SetExtractionModeToLargestRegion(); + connectivityfilter.ColorRegionsOn(); + connectivityfilter.Update(); + Episurf.DeepCopy(connectivityfilter.GetOutput()); + + + zrange = [] + for p in range(0, 3): + + connectivityfilter.AddSpecifiedRegion(p); + connectivityfilter.SetExtractionModeToSpecifiedRegions(); + connectivityfilter.Update(); + connectivityfilter.DeleteSpecifiedRegion(p); + + bds = connectivityfilter.GetOutput().GetBounds() + + if(basalnormal == 'z'): + zrange.append(abs(bds[5] - bds[4])) + elif(basalnormal == 'x'): + zrange.append(abs(bds[1] - bds[0])) + + epiids = zrange.index(max(zrange)) + #RVendoids = zrange.index(min(zrange)) + LVendoids = zrange.index(min(zrange)) + #idlist = set([0,1,2]) + #LVendoids = list(idlist.difference(set([epiids, RVendoids])))[0] + + epiids = 0 + LVendoids = 2 + + # Extracting RV surface + [connectivityfilter.AddSpecifiedRegion(p) for p in range(0,connectivityfilter.GetNumberOfExtractedRegions())] + connectivityfilter.DeleteSpecifiedRegion(epiids); + connectivityfilter.DeleteSpecifiedRegion(LVendoids); + connectivityfilter.SetExtractionModeToSpecifiedRegions(); + #connectivityfilter.SetExtractionModeToSpecifiedRegions(); + connectivityfilter.Update(); + RVEndosurf.DeepCopy(connectivityfilter.GetOutput()); + [connectivityfilter.DeleteSpecifiedRegion(p) for p in range(0,connectivityfilter.GetNumberOfExtractedRegions())] + #connectivityfilter.DeleteSpecifiedRegion(RVendoids); + + + outfilename = 'RV_surf.vtp' + vtk_py.writeXMLPData(RVEndosurf, outfilename) + + # Extracting LV surface + connectivityfilter.AddSpecifiedRegion(LVendoids); + connectivityfilter.SetExtractionModeToSpecifiedRegions(); + connectivityfilter.Update(); + LVEndosurf.DeepCopy(connectivityfilter.GetOutput()); + connectivityfilter.DeleteSpecifiedRegion(LVendoids); + + outfilename = 'LV_surf.vtp' + vtk_py.writeXMLPData(LVEndosurf, outfilename) + + + # Get Epi surface points + for p in range(0, Episurf.GetNumberOfCells()): + ptlist = vtk.vtkIdList() + Episurf.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = Episurf.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + Episurfnodes.InsertUniqueId(ptid) + + + # Get RV surface points + for p in range(0, RVEndosurf.GetNumberOfCells()): + ptlist = vtk.vtkIdList() + RVEndosurf.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = RVEndosurf.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + RVEndosurfnodes.InsertUniqueId(ptid) + + # Get LV surface points + for p in range(0, LVEndosurf.GetNumberOfCells()): + ptlist = vtk.vtkIdList() + LVEndosurf.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = LVEndosurf.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + LVEndosurfnodes.InsertUniqueId(ptid) + + # Get Epi basal edge points + Basalepisurfnodes.DeepCopy(Basalsurfnodes) + Basalepisurfnodes.IntersectWith(Episurfnodes) + + + return Basalsurfnodes, Basalepisurfnodes, Episurfnodes, RVEndosurfnodes, LVEndosurfnodes + + + +def set_pix_intensity(mesh, vtuoutputdir, vtufilename, txtoutputdir, txtfilename): + + + outvtufilename = vtuoutputdir + vtufilename + outtxtfilename = txtoutputdir + txtfilename + + txtfile = open(outtxtfilename, "w"); + + cellpixintensity = mesh.GetCellData().GetScalars("closest_pix_intensity") + print cellpixintensity.GetNumberOfTuples() + + rangeofpixintensity = cellpixintensity.GetValueRange() + + + matid = vtk.vtkIntArray() + matid.SetNumberOfComponents(1) + matid.SetName("Material Id") + + normalized_pix = vtk.vtkFloatArray() + normalized_pix.SetNumberOfComponents(1) + normalized_pix.SetName("Normalized Pixel Intensity") + + for p in range(0, mesh.GetNumberOfCells()): + + pix_intensity = cellpixintensity.GetTuple(p) + normalized_pix_intensity = (pix_intensity[0] - rangeofpixintensity[0])/(rangeofpixintensity[1] - rangeofpixintensity[0]) + + normalized_pix.InsertNextValue(normalized_pix_intensity) + + print >>txtfile, p+1, normalized_pix_intensity + + txtfile.close() + + #mesh.GetCellData().SetActiveScalars("Material Id") + #mesh.GetCellData().SetScalars(matid) + + mesh.GetCellData().SetActiveScalars("Normalized_Pixel_Intensity") + mesh.GetCellData().SetScalars(normalized_pix) + + writer = vtk.vtkXMLUnstructuredGridWriter() + writer.SetFileName(outvtufilename) + writer.SetInput(mesh) + writer.Write(); + +def transform_scale_n_write(mesh, outdirectory, vtufilename): + + newfilename = outdirectory + vtufilename[0:len(vtufilename)-4]+"_scaled_rotated.vtu" + + + bds = mesh.GetBounds() + + trans = vtk.vtkTransform() + trans.Translate(bds[5]/10,0,0) + trans.RotateY(-90) + trans.Scale(0.1, 0.1, 0.1) + + + transfilter = vtk.vtkTransformFilter() + transfilter.SetTransform(trans) + transfilter.SetInput(mesh) + + writer = vtk.vtkXMLUnstructuredGridWriter() + writer.SetFileName(newfilename) + writer.SetInput(transfilter.GetOutput()) + writer.Write() + +def convert_lintets_2_mtv(mesh, outdirectory, name, issavepts, isrotate, basalnormal, tol, epispringcond): + + + rotate = isrotate; + bds = mesh.GetBounds() + if(basalnormal == 'z'): + zoffset = bds[5]; + print "z offset = ", zoffset + elif(basalnormal == 'x'): + zoffset = bds[1]; + print "x offset = ", zoffset + + filename = outdirectory + name + ".grid" + mtvfile = open(filename, 'w') + + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, "Finite element mesh (MLGridFEAdB)" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, "Finite element mesh (GridFE):" + print >>mtvfile, " " + print >>mtvfile, " Number of space dim. = 3 embedded in physical space with dimension 3" + print >>mtvfile, " Number of elements = %5d" %mesh.GetNumberOfCells() + print >>mtvfile, " Number of nodes = %5d" %mesh.GetNumberOfPoints() + print >>mtvfile, " " + print >>mtvfile, " All elements are of the same type : true" + print >>mtvfile, " Max number of nodes in an element: 4" + print >>mtvfile, " Only one material : false" + print >>mtvfile, " Lattice data ? 0" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " 12 boundary indicators: " + print >>mtvfile, " P1" + print >>mtvfile, " P2" + print >>mtvfile, " P3" + print >>mtvfile, " T1" + print >>mtvfile, " T2" + print >>mtvfile, " u1=0" + print >>mtvfile, " u2=0" + print >>mtvfile, " u3=0" + print >>mtvfile, " u1=u1_0" + print >>mtvfile, " u2=u2_0" + print >>mtvfile, " u3=u3_0" + print >>mtvfile, " free" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " Nodal coordinates and nodal boundary indicators," + print >>mtvfile, " the columns contain:" + print >>mtvfile, " - node number" + print >>mtvfile, " - coordinates" + print >>mtvfile, " - no of boundary indicators that are set (ON)" + print >>mtvfile, " - the boundary indicators that are set (ON) if any." + print >>mtvfile, "#" + + + # Get Surface nodes for pressure constraint + Basalsurfnodes, Basalepisurfnodes, Episurfnodes, RVEndosurfnodes, LVEndosurfnodes = extract_biven_surf_nodes(mesh, basalnormal, tol) + + if(issavepts == 1): + ptfilename = outdirectory + name + '_Basalsurfnodes.vtp' + savepoints(mesh, Basalsurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_Basalepisurfnodes.vtp' + savepoints(mesh, Basalepisurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_Episurfnodes.vtp' + savepoints(mesh, Episurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_RVEndosurfnodes.vtp' + savepoints(mesh, RVEndosurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_LVEndosurfnodes.vtp' + savepoints(mesh, LVEndosurfnodes, ptfilename) + + + + + num_bindicator = zeros(mesh.GetNumberOfPoints()); + bindicator = ['']*mesh.GetNumberOfPoints(); + for k in range(0,Episurfnodes.GetNumberOfIds()): + nodeid = Episurfnodes.GetId(k) + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + if(epispringcond==1): + bindicator[nodeid] = bindicator[nodeid] + ' 4' + elif(epispringcond==2): + bindicator[nodeid] = bindicator[nodeid] + ' 4' + else: + bindicator[nodeid] = bindicator[nodeid] + ' 3' + + for k in range(0,LVEndosurfnodes.GetNumberOfIds()): + nodeid = LVEndosurfnodes.GetId(k) + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 1' + + for k in range(0,RVEndosurfnodes.GetNumberOfIds()): + nodeid = RVEndosurfnodes.GetId(k) + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 2' + + for k in range(0,Basalepisurfnodes.GetNumberOfIds()): + nodeid = Basalepisurfnodes.GetId(k) + if(epispringcond==1): + num_bindicator[nodeid] = num_bindicator[nodeid] + 0 + elif(epispringcond==2): + num_bindicator[nodeid] = num_bindicator[nodeid] + 2 + if(rotate == 0): + bindicator[nodeid] = bindicator[nodeid] + ' 4 8' + else: + bindicator[nodeid] = bindicator[nodeid] + ' 4 6' + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 3 + bindicator[nodeid] = bindicator[nodeid] + ' 6 7 8' + + for k in range(0,Basalsurfnodes.GetNumberOfIds()): + nodeid = Basalsurfnodes.GetId(k) + if(rotate == 0): + if(Basalepisurfnodes.IsId(nodeid) == -1): + if(epispringcond==1): + num_bindicator[nodeid] = num_bindicator[nodeid] + 0 + elif(epispringcond==2): + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 8' + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 8' + else: + if(Basalepisurfnodes.IsId(nodeid) == -1): + if(epispringcond==1): + num_bindicator[nodeid] = num_bindicator[nodeid] + 0 + elif(epispringcond==2): + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 6' + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 6' + + #print bindicator + pt = [0,0,0]; + rotatedpt = [0,0,0]; + #num_bindicator = 0; + #bindicator = " "; + for p in range(0, mesh.GetNumberOfPoints()): + if(rotate == 0): + mesh.GetPoints().GetPoint(p,pt); + print >>mtvfile, "%6d ( %11.5e, %11.5e, %11.5e) [%d] %s " %((p+1), pt[0], pt[1], pt[2], num_bindicator[p], bindicator[p] ) + else: + mesh.GetPoints().GetPoint(p,pt); + rotatedpt[0] = (-pt[2]+zoffset)/10.0; + rotatedpt[1] = (pt[1])/10.0; + rotatedpt[2] = (pt[0])/10.0; + + print >>mtvfile, "%6d ( %11.5e, %11.5e, %11.5e) [%d] %s " %((p+1), rotatedpt[0], rotatedpt[1], rotatedpt[2], num_bindicator[p], bindicator[p] ) + + print >>mtvfile, " " + print >>mtvfile, " Element types and connectivity" + print >>mtvfile, " the columns contain:" + print >>mtvfile, " - element number" + print >>mtvfile, " - element type" + print >>mtvfile, " - material number" + print >>mtvfile, " - the global node numbers of the nodes in the element." + print >>mtvfile, "#" + + + materialid = mesh.GetCellData().GetArray('Material Id') + ptid = vtkIdList() + ids = [0,0,0,0,0,0,0,0,0,0]; + + for p in range(0, mesh.GetNumberOfCells()): + mesh.GetCellPoints(p, ptid); + for j in range(0, 4): + ids[j] = int(ptid.GetId(j)); + try: + matid = materialid.GetValue(p) + + except AttributeError: + matid = 1 + + print >>mtvfile, "%5d ElmT4n3D %1d %5d %5d %5d %5d " %((p+1), matid, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1) + + + mtvfile.close() + + + +tol = 1e-1 +parser = argparse.ArgumentParser() +parser.add_argument('--vtk_folder', type=str, required=True) +parser.add_argument('--vtk_filename', type=str, required=True) +parser.add_argument('--mtv_grid_directory', type=str, required=True) +parser.add_argument('--mtv_basename', type=str, required=True) +parser.add_argument('--isepispring', type=int, required=True) +args = parser.parse_args() + + +print "************* Entering vtkmtvtranslator_lintets_v1.py *****************" + +if(args.isepispring): + print "Enforce spring B.C on epi" + + +if (args.vtk_filename[len(args.vtk_filename)-3:len(args.vtk_filename)] == 'vtu'): + mesh = vtk_py.readXMLUGrid(os.path.join(args.vtk_folder, args.vtk_filename)) +else: + mesh = vtk_py.readUGrid(os.path.join(args.vtk_folder, args.vtk_filename)) + +mesh = extract_tetra(mesh) + +convert_lintets_2_mtv(mesh, args.mtv_grid_directory, args.mtv_basename, 1, 1, "z", tol, args.isepispring) + +print "************* Leaving vtkmtvtranslator_lintets_v1.py *****************" diff --git a/vtk_py/vtkmtvtranslator_quadtets_LVonly_v1.py b/vtk_py/vtkmtvtranslator_quadtets_LVonly_v1.py new file mode 100644 index 0000000..5ea740e --- /dev/null +++ b/vtk_py/vtkmtvtranslator_quadtets_LVonly_v1.py @@ -0,0 +1,477 @@ +######################################################################## + +import argparse +import glob +from numpy import * +from sets import Set +from vtk import * +import os + +import vtk_py as vtk_py + +######################################################################## + + + +def extract_tetra(mesh): + + idlist = vtk.vtkIdList() + celltype = mesh.GetCellTypesArray() + for p in range(0, celltype.GetNumberOfTuples()): + if(float(celltype.GetTuple(p)[0]) == 24): + idlist.InsertNextId(p) + + extracted = vtk.vtkExtractCells() + extracted.SetCellList(idlist) + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + extracted.SetInput(mesh) + else: + extracted.SetInputData(mesh) + extracted.Update() + + return extracted.GetOutput() + + + +def writepdata(filename, pdata): + + pdatawriter = vtk.vtkXMLPolyDataWriter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + pdatawriter.SetInput(pdata) + else: + pdatawriter.SetInputData(pdata) + pdatawriter.SetFileName(filename) + pdatawriter.Write() + + + +def savepoints(ugrid, nodeids, ptfilename): + + # View points + viewpts = vtk.vtkPoints() + viewptspdata =vtk.vtkPolyData() + for p in range(0, nodeids.GetNumberOfIds()): + pt = [0,0,0] + pt = ugrid.GetPoints().GetPoint(nodeids.GetId(p)) + viewpts.InsertNextPoint(pt) + + viewptspdata.SetPoints(viewpts) + + maskPoints = vtk.vtkMaskPoints() + maskPoints.SetOnRatio(1); + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + maskPoints.SetInput(viewptspdata); + else: + maskPoints.SetInputData(viewptspdata); + maskPoints.GenerateVerticesOn(); + maskPoints.Update(); + + writepdata(ptfilename, maskPoints.GetOutput()) + + +def extract_LV_surf_nodes(ugrid): + + Basalsurfnodes = vtk.vtkIdList() + Episurfnodes = vtk.vtkIdList() + LVEndosurfnodes = vtk.vtkIdList() + Basalepisurfnodes = vtk.vtkIdList() + + + Episurf = vtk.vtkPolyData() + LVEndosurf = vtk.vtkPolyData() + + Idfilter = vtk.vtkIdFilter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + Idfilter.SetInput(ugrid) + else: + Idfilter.SetInputData(ugrid) + Idfilter.Update() + + geomfilter = vtk.vtkGeometryFilter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + geomfilter.SetInput(Idfilter.GetOutput()) + else: + geomfilter.SetInputData(Idfilter.GetOutput()) + geomfilter.Update() + + cleanpdata = vtk.vtkCleanPolyData() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + cleanpdata.SetInput(geomfilter.GetOutput()) + else: + cleanpdata.SetInputData(geomfilter.GetOutput()) + cleanpdata.Update() + + pdatanormal = vtk.vtkPolyDataNormals() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + pdatanormal.SetInput(cleanpdata.GetOutput()) + else: + pdatanormal.SetInputData(cleanpdata.GetOutput()) + pdatanormal.ComputeCellNormalsOn() + pdatanormal.Update() + + reducedsurfacemesh = vtk.vtkPolyData() + reducedsurfacemesh.DeepCopy(pdatanormal.GetOutput()) + reducedsurfacemesh.BuildLinks() + + + + bds = reducedsurfacemesh.GetBounds() + numcells = reducedsurfacemesh.GetNumberOfCells() + tol = 1e-1; + for p in range(0, numcells): + + ptlist = vtk.vtkIdList() + normvec = reducedsurfacemesh.GetCellData().GetArray("Normals").GetTuple3(p) + + # If cell normal is in 0,0,1 direction + if(abs(vtkMath.Dot(normvec, [1,0,0])) < tol and abs(vtkMath.Dot(normvec, [0,1,0])) < tol): + reducedsurfacemesh.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = reducedsurfacemesh.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + + pt = [0,0,0] + pt = ugrid.GetPoints().GetPoint(ptid) + + if(pt[2] > 0.5*(bds[5] + bds[4])): + Basalsurfnodes.InsertUniqueId(ptid) + + reducedsurfacemesh.DeleteCell(p) + + reducedsurfacemesh.RemoveDeletedCells(); + #reducedsurfacemesh.Update() + + + # Split the surfaces to LVendo, RVendo, Epi + connectivityfilter = vtk.vtkPolyDataConnectivityFilter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + connectivityfilter.SetInput(reducedsurfacemesh) + else: + connectivityfilter.SetInputData(reducedsurfacemesh) + connectivityfilter.Update() + + # Extracting Epi surface + connectivityfilter.SetExtractionModeToLargestRegion(); + connectivityfilter.ColorRegionsOn(); + connectivityfilter.Update(); + Episurf.DeepCopy(connectivityfilter.GetOutput()); + + zrange = [] + for p in range(0, 3): + + connectivityfilter.AddSpecifiedRegion(p); + connectivityfilter.SetExtractionModeToSpecifiedRegions(); + connectivityfilter.Update(); + connectivityfilter.DeleteSpecifiedRegion(p); + + bds = connectivityfilter.GetOutput().GetBounds() + zrange.append(abs(bds[5] - bds[4])) + + epiids = zrange.index(max(zrange)) + RVendoids = zrange.index(min(zrange)) + idlist = set([0,1]) + #LVendoids = list(idlist.difference(set([epiids, RVendoids])))[0] + LVendoids = list(idlist.difference(set([epiids])))[0] + + # Extracting LV surface + connectivityfilter.AddSpecifiedRegion(LVendoids); + connectivityfilter.SetExtractionModeToSpecifiedRegions(); + connectivityfilter.Update(); + LVEndosurf.DeepCopy(connectivityfilter.GetOutput()); + connectivityfilter.DeleteSpecifiedRegion(LVendoids); + + # Get Epi surface points + for p in range(0, Episurf.GetNumberOfCells()): + ptlist = vtk.vtkIdList() + Episurf.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = Episurf.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + Episurfnodes.InsertUniqueId(ptid) + + + # Get LV surface points + for p in range(0, LVEndosurf.GetNumberOfCells()): + ptlist = vtk.vtkIdList() + LVEndosurf.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = LVEndosurf.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + LVEndosurfnodes.InsertUniqueId(ptid) + + # Get Epi basal edge points + Basalepisurfnodes.DeepCopy(Basalsurfnodes) + Basalepisurfnodes.IntersectWith(Episurfnodes) + + + return Basalsurfnodes, Basalepisurfnodes, Episurfnodes, LVEndosurfnodes + + + +def set_pix_intensity(mesh, vtuoutputdir, vtufilename, txtoutputdir, txtfilename): + + + outvtufilename = vtuoutputdir + vtufilename + outtxtfilename = txtoutputdir + txtfilename + + txtfile = open(outtxtfilename, "w"); + + cellpixintensity = mesh.GetCellData().GetScalars("closest_pix_intensity") + print cellpixintensity.GetNumberOfTuples() + + rangeofpixintensity = cellpixintensity.GetValueRange() + + + matid = vtk.vtkIntArray() + matid.SetNumberOfComponents(1) + matid.SetName("Material Id") + + normalized_pix = vtk.vtkFloatArray() + normalized_pix.SetNumberOfComponents(1) + normalized_pix.SetName("Normalized Pixel Intensity") + + for p in range(0, mesh.GetNumberOfCells()): + + pix_intensity = cellpixintensity.GetTuple(p) + normalized_pix_intensity = (pix_intensity[0] - rangeofpixintensity[0])/(rangeofpixintensity[1] - rangeofpixintensity[0]) + + normalized_pix.InsertNextValue(normalized_pix_intensity) + + print >>txtfile, p+1, normalized_pix_intensity + + txtfile.close() + + #mesh.GetCellData().SetActiveScalars("Material Id") + #mesh.GetCellData().SetScalars(matid) + + mesh.GetCellData().SetActiveScalars("Normalized_Pixel_Intensity") + mesh.GetCellData().SetScalars(normalized_pix) + + writer = vtk.vtkXMLUnstructuredGridWriter() + writer.SetFileName(outvtufilename) + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + writer.SetInput(mesh) + else: + writer.SetInputData(mesh) + writer.Write(); + +def transform_scale_n_write(mesh, outdirectory, vtufilename): + + newfilename = outdirectory + vtufilename[0:len(vtufilename)-4]+"_scaled_rotated.vtu" + + + bds = mesh.GetBounds() + + trans = vtk.vtkTransform() + trans.Translate(bds[5]/10,0,0) + trans.RotateY(-90) + trans.Scale(0.1, 0.1, 0.1) + + + transfilter = vtk.vtkTransformFilter() + transfilter.SetTransform(trans) + transfilter.SetInput(mesh) + + writer = vtk.vtkXMLUnstructuredGridWriter() + writer.SetFileName(newfilename) + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + writer.SetInput(transfilter.GetOutput()) + else: + writer.SetInputData(transfilter.GetOutput()) + writer.Write() + +def convert_quadtets_2_mtv(mesh, outdirectory, name, issavepts, isrotate, basalnormal, tol, epispringcond, scale): + + + rotate = isrotate; + bds = mesh.GetBounds() + if(basalnormal == 'z'): + zoffset = bds[5]; + print "z offset = ", zoffset + elif(basalnormal == 'x'): + zoffset = bds[1]; + print "x offset = ", zoffset + + filename = outdirectory + name + ".grid" + mtvfile = open(filename, 'w') + + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, "Finite element mesh (MLGridFEAdB)" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, "Finite element mesh (GridFE):" + print >>mtvfile, " " + print >>mtvfile, " Number of space dim. = 3 embedded in physical space with dimension 3" + print >>mtvfile, " Number of elements = %5d" %mesh.GetNumberOfCells() + print >>mtvfile, " Number of nodes = %5d" %mesh.GetNumberOfPoints() + print >>mtvfile, " " + print >>mtvfile, " All elements are of the same type : true" + print >>mtvfile, " Max number of nodes in an element: 10" + print >>mtvfile, " Only one material : false" + print >>mtvfile, " Lattice data ? 0" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " 12 boundary indicators: " + print >>mtvfile, " P1" + print >>mtvfile, " P2" + print >>mtvfile, " P3" + print >>mtvfile, " T1" + print >>mtvfile, " T2" + print >>mtvfile, " u1=0" + print >>mtvfile, " u2=0" + print >>mtvfile, " u3=0" + print >>mtvfile, " u1=u1_0" + print >>mtvfile, " u2=u2_0" + print >>mtvfile, " u3=u3_0" + print >>mtvfile, " free" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " Nodal coordinates and nodal boundary indicators," + print >>mtvfile, " the columns contain:" + print >>mtvfile, " - node number" + print >>mtvfile, " - coordinates" + print >>mtvfile, " - no of boundary indicators that are set (ON)" + print >>mtvfile, " - the boundary indicators that are set (ON) if any." + print >>mtvfile, "#" + + + # Get Surface nodes for pressure constraint + Basalsurfnodes, Basalepisurfnodes, Episurfnodes, LVEndosurfnodes = extract_LV_surf_nodes(mesh) + + + if(issavepts == 1): + ptfilename = outdirectory + name + '_Basalsurfnodes.vtp' + savepoints(mesh, Basalsurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_Basalepisurfnodes.vtp' + savepoints(mesh, Basalepisurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_Episurfnodes.vtp' + savepoints(mesh, Episurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_LVEndosurfnodes.vtp' + savepoints(mesh, LVEndosurfnodes, ptfilename) + + + + num_bindicator = zeros(mesh.GetNumberOfPoints()); + bindicator = ['']*mesh.GetNumberOfPoints(); + + for k in range(0,Episurfnodes.GetNumberOfIds()): + nodeid = Episurfnodes.GetId(k) + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + if(epispringcond): + bindicator[nodeid] = bindicator[nodeid] + ' 4' + else: + bindicator[nodeid] = bindicator[nodeid] + ' 3' + + for k in range(0,LVEndosurfnodes.GetNumberOfIds()): + nodeid = LVEndosurfnodes.GetId(k) + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 1' + + for k in range(0,Basalepisurfnodes.GetNumberOfIds()): + nodeid = Basalepisurfnodes.GetId(k) + if(epispringcond): + num_bindicator[nodeid] = num_bindicator[nodeid] + 0 + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 3 + bindicator[nodeid] = bindicator[nodeid] + ' 6 7 8' + + for k in range(0,Basalsurfnodes.GetNumberOfIds()): + nodeid = Basalsurfnodes.GetId(k) + if(rotate == 0): + if(Basalepisurfnodes.IsId(nodeid) == -1): + if(epispringcond): + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 13' + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 8' + else: + if(Basalepisurfnodes.IsId(nodeid) == -1): + if(epispringcond): + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 13' + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 6' + + + #print bindicator + pt = [0,0,0]; + rotatedpt = [0,0,0]; + #num_bindicator = 0; + #bindicator = " "; + for p in range(0, mesh.GetNumberOfPoints()): + if(rotate == 0): + mesh.GetPoints().GetPoint(p,pt); + print >>mtvfile, "%6d ( %11.5e, %11.5e, %11.5e) [%d] %s " %((p+1), pt[0], pt[1], pt[2], num_bindicator[p], bindicator[p] ) + else: + mesh.GetPoints().GetPoint(p,pt); + rotatedpt[0] = (-pt[2]+zoffset)/1.0; + rotatedpt[1] = (pt[1])/1.0; + rotatedpt[2] = (pt[0])/1.0; + + print >>mtvfile, "%6d ( %11.5e, %11.5e, %11.5e) [%d] %s " %((p+1), rotatedpt[0], rotatedpt[1], rotatedpt[2], num_bindicator[p], bindicator[p] ) + + print >>mtvfile, " " + print >>mtvfile, " Element types and connectivity" + print >>mtvfile, " the columns contain:" + print >>mtvfile, " - element number" + print >>mtvfile, " - element type" + print >>mtvfile, " - material number" + print >>mtvfile, " - the global node numbers of the nodes in the element." + print >>mtvfile, "#" + + + materialid = mesh.GetCellData().GetArray('Material Id') + ptid = vtkIdList() + ids = [0,0,0,0,0,0,0,0,0,0]; + + for p in range(0, mesh.GetNumberOfCells()): + mesh.GetCellPoints(p, ptid); + for j in range(0, 10): + ids[j] = int(ptid.GetId(j)); + try: + matid = materialid.GetValue(p) + + except AttributeError: + matid = 1 + + print >>mtvfile, "%5d ElmT10n3D %1d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d " %((p+1), matid, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1) + + + mtvfile.close() + + +tol = 1e-1 +parser = argparse.ArgumentParser() +parser.add_argument('--vtk_folder', type=str, required=True) +parser.add_argument('--vtk_filename', type=str, required=True) +parser.add_argument('--mtv_grid_directory', type=str, required=True) +parser.add_argument('--mtv_basename', type=str, required=True) +parser.add_argument('--isepispring', type=int, required=True) +parser.add_argument('--scale', type=float, required=True) +args = parser.parse_args() + + +print "************* Entering vtkmtvtranslator_quadtets_v1.py *****************" + +if(args.isepispring): + print "Enforce spring B.C on epi" + + +if (args.vtk_filename[len(args.vtk_filename)-3:len(args.vtk_filename)] == 'vtu'): + print os.path.join(args.vtk_folder, args.vtk_filename) + mesh = vtk_py.readXMLUGrid(os.path.join(args.vtk_folder, args.vtk_filename)) +else: + mesh = vtk_py.readUGrid(os.path.join(args.vtk_folder, args.vtk_filename)) + +#mesh = extract_tetra(mesh) + +convert_quadtets_2_mtv(mesh, args.mtv_grid_directory, args.mtv_basename, 1, 1, "z", tol, args.isepispring, args.scale) + +print "************* Leaving vtkmtvtranslator_quadtets_v1.py *****************" + + diff --git a/vtk_py/vtkmtvtranslator_quadtets_v1.py b/vtk_py/vtkmtvtranslator_quadtets_v1.py new file mode 100644 index 0000000..692df9d --- /dev/null +++ b/vtk_py/vtkmtvtranslator_quadtets_v1.py @@ -0,0 +1,561 @@ +######################################################################## + +import argparse +import glob +from numpy import * +from sets import Set +from vtk import * +import os + +import vtk_py as vtk_py + +######################################################################## + + + + +def extract_tetra(mesh): + + idlist = vtk.vtkIdList() + celltype = mesh.GetCellTypesArray() + for p in range(0, celltype.GetNumberOfTuples()): + if(float(celltype.GetTuple(p)[0]) == 24): + idlist.InsertNextId(p) + + extracted = vtk.vtkExtractCells() + extracted.SetCellList(idlist) + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + extracted.SetInput(mesh) + else: + extracted.SetInputData(mesh) + extracted.Update() + + return extracted.GetOutput() + + + +def writepdata(filename, pdata): + + pdatawriter = vtk.vtkXMLPolyDataWriter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + pdatawriter.SetInput(pdata) + else: + pdatawriter.SetInputData(pdata) + pdatawriter.SetFileName(filename) + pdatawriter.Write() + + + +def savepoints(ugrid, nodeids, ptfilename): + + # View points + viewpts = vtk.vtkPoints() + viewptspdata =vtk.vtkPolyData() + for p in range(0, nodeids.GetNumberOfIds()): + pt = [0,0,0] + pt = ugrid.GetPoints().GetPoint(nodeids.GetId(p)) + viewpts.InsertNextPoint(pt) + + viewptspdata.SetPoints(viewpts) + + maskPoints = vtk.vtkMaskPoints() + maskPoints.SetOnRatio(1); + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + maskPoints.SetInput(viewptspdata); + else: + maskPoints.SetInputData(viewptspdata); + maskPoints.GenerateVerticesOn(); + maskPoints.Update(); + + writepdata(ptfilename, maskPoints.GetOutput()) + + +def extract_biven_surf_nodes(ugrid, basalnormal, tol): + + Basalsurfnodes = vtk.vtkIdList() + Episurfnodes = vtk.vtkIdList() + RVEndosurfnodes = vtk.vtkIdList() + LVEndosurfnodes = vtk.vtkIdList() + Basalepisurfnodes = vtk.vtkIdList() + + Episurf = vtk.vtkPolyData() + LVEndosurf = vtk.vtkPolyData() + RVEndosurf = vtk.vtkPolyData() + + Idfilter = vtk.vtkIdFilter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + Idfilter.SetInput(ugrid) + else: + Idfilter.SetInputData(ugrid) + Idfilter.Update() + + geomfilter = vtk.vtkGeometryFilter() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + geomfilter.SetInput(Idfilter.GetOutput()) + else: + geomfilter.SetInputData(Idfilter.GetOutput()) + geomfilter.Update() + + cleanpdata = vtk.vtkCleanPolyData() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + cleanpdata.SetInput(geomfilter.GetOutput()) + else: + cleanpdata.SetInputData(geomfilter.GetOutput()) + cleanpdata.Update() + + pdatanormal = vtk.vtkPolyDataNormals() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + pdatanormal.SetInput(cleanpdata.GetOutput()) + else: + pdatanormal.SetInputData(cleanpdata.GetOutput()) + pdatanormal.ComputeCellNormalsOn() + pdatanormal.Update() + + #vtk_py.writeXMLPData(pdatanormal.GetOutput(), "test.vtp") + + reducedsurfacemesh = vtk.vtkPolyData() + reducedsurfacemesh.DeepCopy(pdatanormal.GetOutput()) + reducedsurfacemesh.BuildLinks() + + bds = reducedsurfacemesh.GetBounds() + numcells = reducedsurfacemesh.GetNumberOfCells() + for p in range(0, numcells): + + ptlist = vtk.vtkIdList() + normvec = reducedsurfacemesh.GetCellData().GetArray("Normals").GetTuple3(p) + + # If cell normal is in 0,0,1 direction + if(basalnormal == 'z'): + if(abs(vtkMath.Dot(normvec, [1,0,0])) < tol and abs(vtkMath.Dot(normvec, [0,1,0])) < tol): + reducedsurfacemesh.GetCellPoints(p, ptlist) + count_nodes_at_base = 0; + for j in range(0, ptlist.GetNumberOfIds()): + ptid = reducedsurfacemesh.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + + pt = [0,0,0] + pt = ugrid.GetPoints().GetPoint(ptid) + + if(pt[2] > 0.5*(bds[5] + bds[4])): + Basalsurfnodes.InsertUniqueId(ptid) + + if(pt[2] > bds[5] - tol): + count_nodes_at_base = count_nodes_at_base + 1 + + if(count_nodes_at_base == 3): + reducedsurfacemesh.DeleteCell(p) + + elif(basalnormal =='x'): + + if(abs(vtkMath.Dot(normvec, [0,0,1])) < tol and abs(vtkMath.Dot(normvec, [0,1,0])) < tol): + reducedsurfacemesh.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = reducedsurfacemesh.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + + pt = [0,0,0] + pt = ugrid.GetPoints().GetPoint(ptid) + + + if(pt[0] < bds[0] + tol): + Basalsurfnodes.InsertUniqueId(ptid) + + if(pt[0] < bds[0] + tol): + reducedsurfacemesh.DeleteCell(p) + + + + reducedsurfacemesh.RemoveDeletedCells(); + #reducedsurfacemesh.Update() + + + # Split the surfaces to LVendo, RVendo, Epi + connectivityfilter = vtk.vtkPolyDataConnectivityFilter() + connectivityfilter.SetScalarConnectivity(0); + connectivityfilter.ColorRegionsOn(); + connectivityfilter.SetExtractionModeToAllRegions() + if(vtk.vtkVersion.GetVTKMajorVersion() < 6): + connectivityfilter.SetInput(reducedsurfacemesh) + else: + connectivityfilter.SetInputData(reducedsurfacemesh) + connectivityfilter.Update() + + print "Number of connected regions = ", connectivityfilter.GetNumberOfExtractedRegions() + vtk_py.writeXMLPData(connectivityfilter.GetOutput(), "connectedregion.vtp") + + + # Extracting Epi surface + connectivityfilter.SetExtractionModeToLargestRegion(); + connectivityfilter.ColorRegionsOn(); + connectivityfilter.Update(); + Episurf.DeepCopy(connectivityfilter.GetOutput()); + + + zrange = [] + for p in range(0, 3): + + connectivityfilter.AddSpecifiedRegion(p); + connectivityfilter.SetExtractionModeToSpecifiedRegions(); + connectivityfilter.Update(); + connectivityfilter.DeleteSpecifiedRegion(p); + + bds = connectivityfilter.GetOutput().GetBounds() + + if(basalnormal == 'z'): + zrange.append(abs(bds[5] - bds[4])) + elif(basalnormal == 'x'): + zrange.append(abs(bds[1] - bds[0])) + + epiids = zrange.index(max(zrange)) + #RVendoids = zrange.index(min(zrange)) + LVendoids = zrange.index(min(zrange)) + #idlist = set([0,1,2]) + #LVendoids = list(idlist.difference(set([epiids, RVendoids])))[0] + + # LKK + epiids = [0,4] #[1, 8] + LVendoids = [1,3] #[2, 13] + # CRT02 + epiids = [0] #[1, 8] + LVendoids = [1] #[2, 13] + # LKK COARSE + epiids = [1] #[1, 8] + LVendoids = [0] #[2, 13] + + # Extracting RV surface + [connectivityfilter.AddSpecifiedRegion(p) for p in range(0,connectivityfilter.GetNumberOfExtractedRegions())] + [connectivityfilter.DeleteSpecifiedRegion(p) for p in epiids]; + [connectivityfilter.DeleteSpecifiedRegion(p) for p in LVendoids]; + connectivityfilter.SetExtractionModeToSpecifiedRegions(); + #connectivityfilter.SetExtractionModeToSpecifiedRegions(); + connectivityfilter.Update(); + RVEndosurf.DeepCopy(connectivityfilter.GetOutput()); + [connectivityfilter.DeleteSpecifiedRegion(p) for p in range(0,connectivityfilter.GetNumberOfExtractedRegions())] + #connectivityfilter.DeleteSpecifiedRegion(RVendoids); + + + outfilename = 'RV_surf.vtp' + vtk_py.writeXMLPData(RVEndosurf, outfilename) + + # Extracting LV surface + [connectivityfilter.AddSpecifiedRegion(p) for p in LVendoids]; + connectivityfilter.SetExtractionModeToSpecifiedRegions(); + connectivityfilter.Update(); + LVEndosurf.DeepCopy(connectivityfilter.GetOutput()); + [connectivityfilter.DeleteSpecifiedRegion(p) for p in LVendoids]; + + outfilename = 'LV_surf.vtp' + vtk_py.writeXMLPData(LVEndosurf, outfilename) + + + # Get Epi surface points + for p in range(0, Episurf.GetNumberOfCells()): + ptlist = vtk.vtkIdList() + Episurf.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = Episurf.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + Episurfnodes.InsertUniqueId(ptid) + + + # Get RV surface points + for p in range(0, RVEndosurf.GetNumberOfCells()): + ptlist = vtk.vtkIdList() + RVEndosurf.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = RVEndosurf.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + RVEndosurfnodes.InsertUniqueId(ptid) + + # Get LV surface points + for p in range(0, LVEndosurf.GetNumberOfCells()): + ptlist = vtk.vtkIdList() + LVEndosurf.GetCellPoints(p, ptlist) + for j in range(0, ptlist.GetNumberOfIds()): + ptid = LVEndosurf.GetPointData().GetArray("vtkIdFilter_Ids").GetValue(ptlist.GetId(j)) + LVEndosurfnodes.InsertUniqueId(ptid) + + # Get Epi basal edge points + Basalepisurfnodes.DeepCopy(Basalsurfnodes) + Basalepisurfnodes.IntersectWith(Episurfnodes) + + + return Basalsurfnodes, Basalepisurfnodes, Episurfnodes, RVEndosurfnodes, LVEndosurfnodes + + + +def set_pix_intensity(mesh, vtuoutputdir, vtufilename, txtoutputdir, txtfilename): + + + outvtufilename = vtuoutputdir + vtufilename + outtxtfilename = txtoutputdir + txtfilename + + txtfile = open(outtxtfilename, "w"); + + cellpixintensity = mesh.GetCellData().GetScalars("closest_pix_intensity") + print cellpixintensity.GetNumberOfTuples() + + rangeofpixintensity = cellpixintensity.GetValueRange() + + + matid = vtk.vtkIntArray() + matid.SetNumberOfComponents(1) + matid.SetName("Material Id") + + normalized_pix = vtk.vtkFloatArray() + normalized_pix.SetNumberOfComponents(1) + normalized_pix.SetName("Normalized Pixel Intensity") + + for p in range(0, mesh.GetNumberOfCells()): + + pix_intensity = cellpixintensity.GetTuple(p) + normalized_pix_intensity = (pix_intensity[0] - rangeofpixintensity[0])/(rangeofpixintensity[1] - rangeofpixintensity[0]) + + normalized_pix.InsertNextValue(normalized_pix_intensity) + + print >>txtfile, p+1, normalized_pix_intensity + + txtfile.close() + + #mesh.GetCellData().SetActiveScalars("Material Id") + #mesh.GetCellData().SetScalars(matid) + + mesh.GetCellData().SetActiveScalars("Normalized_Pixel_Intensity") + mesh.GetCellData().SetScalars(normalized_pix) + + writer = vtk.vtkXMLUnstructuredGridWriter() + writer.SetFileName(outvtufilename) + writer.SetInput(mesh) + writer.Write(); + +def transform_scale_n_write(mesh, outdirectory, vtufilename): + + newfilename = outdirectory + vtufilename[0:len(vtufilename)-4]+"_scaled_rotated.vtu" + + + bds = mesh.GetBounds() + + trans = vtk.vtkTransform() + trans.Translate(bds[5]/10,0,0) + trans.RotateY(-90) + trans.Scale(0.1, 0.1, 0.1) + + + transfilter = vtk.vtkTransformFilter() + transfilter.SetTransform(trans) + transfilter.SetInput(mesh) + + writer = vtk.vtkXMLUnstructuredGridWriter() + writer.SetFileName(newfilename) + writer.SetInput(transfilter.GetOutput()) + writer.Write() + +def convert_quadtets_2_mtv(mesh, outdirectory, name, issavepts, isrotate, basalnormal, tol, epispringcond): + + + rotate = isrotate; + bds = mesh.GetBounds() + if(basalnormal == 'z'): + zoffset = bds[5]; + print "z offset = ", zoffset + elif(basalnormal == 'x'): + zoffset = bds[1]; + print "x offset = ", zoffset + + filename = outdirectory + name + ".grid" + mtvfile = open(filename, 'w') + + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, "Finite element mesh (MLGridFEAdB)" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, "Finite element mesh (GridFE):" + print >>mtvfile, " " + print >>mtvfile, " Number of space dim. = 3 embedded in physical space with dimension 3" + print >>mtvfile, " Number of elements = %5d" %mesh.GetNumberOfCells() + print >>mtvfile, " Number of nodes = %5d" %mesh.GetNumberOfPoints() + print >>mtvfile, " " + print >>mtvfile, " All elements are of the same type : true" + print >>mtvfile, " Max number of nodes in an element: 10" + print >>mtvfile, " Only one material : false" + print >>mtvfile, " Lattice data ? 0" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " 12 boundary indicators: " + print >>mtvfile, " P1" + print >>mtvfile, " P2" + print >>mtvfile, " P3" + print >>mtvfile, " T1" + print >>mtvfile, " T2" + print >>mtvfile, " u1=0" + print >>mtvfile, " u2=0" + print >>mtvfile, " u3=0" + print >>mtvfile, " u1=u1_0" + print >>mtvfile, " u2=u2_0" + print >>mtvfile, " u3=u3_0" + print >>mtvfile, " free" + print >>mtvfile, " " + print >>mtvfile, " " + print >>mtvfile, " Nodal coordinates and nodal boundary indicators," + print >>mtvfile, " the columns contain:" + print >>mtvfile, " - node number" + print >>mtvfile, " - coordinates" + print >>mtvfile, " - no of boundary indicators that are set (ON)" + print >>mtvfile, " - the boundary indicators that are set (ON) if any." + print >>mtvfile, "#" + + + # Get Surface nodes for pressure constraint + Basalsurfnodes, Basalepisurfnodes, Episurfnodes, RVEndosurfnodes, LVEndosurfnodes = extract_biven_surf_nodes(mesh, basalnormal, tol) + + if(issavepts == 1): + ptfilename = outdirectory + name + '_Basalsurfnodes.vtp' + savepoints(mesh, Basalsurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_Basalepisurfnodes.vtp' + savepoints(mesh, Basalepisurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_Episurfnodes.vtp' + savepoints(mesh, Episurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_RVEndosurfnodes.vtp' + savepoints(mesh, RVEndosurfnodes, ptfilename) + + ptfilename = outdirectory + name + '_LVEndosurfnodes.vtp' + savepoints(mesh, LVEndosurfnodes, ptfilename) + + + + + num_bindicator = zeros(mesh.GetNumberOfPoints()); + bindicator = ['']*mesh.GetNumberOfPoints(); + for k in range(0,Episurfnodes.GetNumberOfIds()): + nodeid = Episurfnodes.GetId(k) + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + if(epispringcond==1): + bindicator[nodeid] = bindicator[nodeid] + ' 4' + elif(epispringcond==2): + bindicator[nodeid] = bindicator[nodeid] + ' 4' + else: + bindicator[nodeid] = bindicator[nodeid] + ' 3' + + for k in range(0,LVEndosurfnodes.GetNumberOfIds()): + nodeid = LVEndosurfnodes.GetId(k) + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 1' + + for k in range(0,RVEndosurfnodes.GetNumberOfIds()): + nodeid = RVEndosurfnodes.GetId(k) + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 2' + + for k in range(0,Basalepisurfnodes.GetNumberOfIds()): + nodeid = Basalepisurfnodes.GetId(k) + if(epispringcond==1): + num_bindicator[nodeid] = num_bindicator[nodeid] + 0 + elif(epispringcond==2): + num_bindicator[nodeid] = num_bindicator[nodeid] + 2 + if(rotate == 0): + bindicator[nodeid] = bindicator[nodeid] + ' 4 8' + else: + bindicator[nodeid] = bindicator[nodeid] + ' 4 6' + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 3 + bindicator[nodeid] = bindicator[nodeid] + ' 6 7 8' + + for k in range(0,Basalsurfnodes.GetNumberOfIds()): + nodeid = Basalsurfnodes.GetId(k) + if(rotate == 0): + if(Basalepisurfnodes.IsId(nodeid) == -1): + if(epispringcond==1): + num_bindicator[nodeid] = num_bindicator[nodeid] + 0 + elif(epispringcond==2): + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 8' + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 8' + else: + if(Basalepisurfnodes.IsId(nodeid) == -1): + if(epispringcond==1): + num_bindicator[nodeid] = num_bindicator[nodeid] + 0 + elif(epispringcond==2): + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 6' + else: + num_bindicator[nodeid] = num_bindicator[nodeid] + 1 + bindicator[nodeid] = bindicator[nodeid] + ' 6' + + #print bindicator + pt = [0,0,0]; + rotatedpt = [0,0,0]; + #num_bindicator = 0; + #bindicator = " "; + for p in range(0, mesh.GetNumberOfPoints()): + if(rotate == 0): + mesh.GetPoints().GetPoint(p,pt); + print >>mtvfile, "%6d ( %11.5e, %11.5e, %11.5e) [%d] %s " %((p+1), pt[0], pt[1], pt[2], num_bindicator[p], bindicator[p] ) + else: + mesh.GetPoints().GetPoint(p,pt); + rotatedpt[0] = (-pt[2]+zoffset)/10.0; + rotatedpt[1] = (pt[1])/10.0; + rotatedpt[2] = (pt[0])/10.0; + + print >>mtvfile, "%6d ( %11.5e, %11.5e, %11.5e) [%d] %s " %((p+1), rotatedpt[0], rotatedpt[1], rotatedpt[2], num_bindicator[p], bindicator[p] ) + + print >>mtvfile, " " + print >>mtvfile, " Element types and connectivity" + print >>mtvfile, " the columns contain:" + print >>mtvfile, " - element number" + print >>mtvfile, " - element type" + print >>mtvfile, " - material number" + print >>mtvfile, " - the global node numbers of the nodes in the element." + print >>mtvfile, "#" + + + materialid = mesh.GetCellData().GetArray('Material Id') + ptid = vtkIdList() + ids = [0,0,0,0,0,0,0,0,0,0]; + + for p in range(0, mesh.GetNumberOfCells()): + mesh.GetCellPoints(p, ptid); + for j in range(0, 10): + ids[j] = int(ptid.GetId(j)); + try: + matid = materialid.GetValue(p) + + except AttributeError: + matid = 1 + + print >>mtvfile, "%5d ElmT10n3D %1d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d " %((p+1), matid, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1) + + + mtvfile.close() + + + +tol = 1e-1 +parser = argparse.ArgumentParser() +parser.add_argument('--vtk_folder', type=str, required=True) +parser.add_argument('--vtk_filename', type=str, required=True) +parser.add_argument('--mtv_grid_directory', type=str, required=True) +parser.add_argument('--mtv_basename', type=str, required=True) +parser.add_argument('--isepispring', type=int, required=True) +args = parser.parse_args() + + +print "************* Entering vtkmtvtranslator_quadtets_v1.py *****************" + +if(args.isepispring): + print "Enforce spring B.C on epi" + + +if (args.vtk_filename[len(args.vtk_filename)-3:len(args.vtk_filename)] == 'vtu'): + mesh = vtk_py.readXMLUGrid(os.path.join(args.vtk_folder, args.vtk_filename)) +else: + mesh = vtk_py.readUGrid(os.path.join(args.vtk_folder, args.vtk_filename)) + +mesh = extract_tetra(mesh) + +convert_quadtets_2_mtv(mesh, args.mtv_grid_directory, args.mtv_basename, 1, 1, "z", tol, args.isepispring) + +print "************* Leaving vtkmtvtranslator_quadtets_v1.py *****************" diff --git a/vtk_py/writeFiberOrientationFileForAbaqus.py b/vtk_py/writeFiberOrientationFileForAbaqus.py new file mode 100644 index 0000000..72f3565 --- /dev/null +++ b/vtk_py/writeFiberOrientationFileForAbaqus.py @@ -0,0 +1,46 @@ +######################################################################## + +import sys + +from readUGrid import * + +######################################################################## + +def writeFiberOrientationFileForAbaqus(mesh, + fiber_orientation_file_name, + eF_field_name="eF", + eS_field_name="eS", + sep=", ", + verbose=True): + if (verbose): print "*** writeFiberOrientationFileForAbaqus ***" + + orientation_file = open(fiber_orientation_file_name, "w") + orientation_file.write(", 1., 0., 0., 0., 1., 0." + "\n") + + nb_cells = mesh.GetNumberOfCells() + + eF_array = mesh.GetCellData().GetArray(eF_field_name) + eS_array = mesh.GetCellData().GetArray(eS_field_name) + + for num_cell in range(nb_cells): + eF = eF_array.GetTuple(num_cell) + eS = eS_array.GetTuple(num_cell) + + line = str(num_cell+1) + for k in range(3): line += sep + str(eF[k]) + for k in range(3): line += sep + str(eS[k]) + line += "\n" + orientation_file.write(line) + + orientation_file.close() + +if (__name__ == "__main__"): + assert (len(sys.argv) in [2,3]), "Number of arguments must be 1 or 2. Aborting." + if (len(sys.argv) == 2): + mesh_file_name = sys.argv[1] + "-Mesh.vtk" + fiber_orientation_file_name = sys.argv[1] + "-Orientation.inp" + elif (len(sys.argv) == 3): + mesh_file_name = sys.argv[1] + fiber_orientation_file_name = sys.argv[2] + mesh = readUGrid(mesh_file_name) + writeFiberOrientationFileForAbaqus(mesh, fiber_orientation_file_name) diff --git a/vtk_py/writeFiberOrientationFileForAbaqus.pyc b/vtk_py/writeFiberOrientationFileForAbaqus.pyc new file mode 100644 index 0000000..8cea83d Binary files /dev/null and b/vtk_py/writeFiberOrientationFileForAbaqus.pyc differ diff --git a/vtk_py/writeFiberOrientationFileForGNUPlot.py b/vtk_py/writeFiberOrientationFileForGNUPlot.py new file mode 100644 index 0000000..e9a86b0 --- /dev/null +++ b/vtk_py/writeFiberOrientationFileForGNUPlot.py @@ -0,0 +1,63 @@ +######################################################################## + +import sys +import math +import random +import numpy +import vtk + +######################################################################## + +def writeFiberOrientationFileForGNUPlot(angles_end, + angles_epi, + fiber_orientation_file_name, + verbose=True): + + if (verbose): print '*** writeFiberOrientationFileForGNUPlot ***' + + assert (len(angles_end) == len(angles_epi)), "angles_end and angle_epi must have same length (nb_long_nodes). Aborting." + nb_long_nodes = len(angles_end) + dz = 1./(nb_long_nodes-1) + nb_circ_nodes = len(angles_end[0]) + for angles in angles_end+angles_epi: + assert (len(angles) == nb_circ_nodes), "angles lists must have same length (nb_circ_nodes). Aborting." + dt = 360./nb_circ_nodes + + fiber_orientation_file = open(fiber_orientation_file_name, 'w') + fiber_orientation_file.write('# t ang_end ang_epi z\n') + + nb_t = 12 + for num_t in range(nb_t+1): + t = float(num_t) / nb_t * 360 + i_t = int(t/dt/1.000001) + zeta = (t - i_t*dt) / dt + + nb_z = 10 + for num_z in range(nb_z+1): + z = float(num_z) / nb_z + i_z = int(z/dz/1.000001) + eta = (z - i_z*dz) / dz + + t_ii_end = angles_end[i_z][i_t%nb_circ_nodes] + t_ji_end = angles_end[i_z][(i_t+1)%nb_circ_nodes] + t_ij_end = angles_end[(i_z+1)][i_t%nb_circ_nodes] + t_jj_end = angles_end[(i_z+1)][(i_t+1)%nb_circ_nodes] + t_ii_epi = angles_epi[i_z][i_t%nb_circ_nodes] + t_ji_epi = angles_epi[i_z][(i_t+1)%nb_circ_nodes] + t_ij_epi = angles_epi[(i_z+1)][i_t%nb_circ_nodes] + t_jj_epi = angles_epi[(i_z+1)][(i_t+1)%nb_circ_nodes] + + fiber_angle_end = t_ii_end * (1 - zeta - eta + zeta*eta) \ + + t_ji_end * (zeta - zeta*eta) \ + + t_ij_end * (eta - zeta*eta) \ + + t_jj_end * (zeta*eta) + fiber_angle_epi = t_ii_epi * (1 - zeta - eta + zeta*eta) \ + + t_ji_epi * (zeta - zeta*eta) \ + + t_ij_epi * (eta - zeta*eta) \ + + t_jj_epi * (zeta*eta) + + fiber_orientation_file.write(" ".join([str(x) for x in [t, fiber_angle_end, fiber_angle_epi, z]]) + "\n") + + fiber_orientation_file.write("\n") + + fiber_orientation_file.close() diff --git a/vtk_py/writeFiberOrientationFileForGNUPlot.pyc b/vtk_py/writeFiberOrientationFileForGNUPlot.pyc new file mode 100644 index 0000000..246c978 Binary files /dev/null and b/vtk_py/writeFiberOrientationFileForGNUPlot.pyc differ diff --git a/vtk_py/writePData.py b/vtk_py/writePData.py new file mode 100644 index 0000000..da1d2db --- /dev/null +++ b/vtk_py/writePData.py @@ -0,0 +1,17 @@ +######################################################################## + +import vtk + +######################################################################## + +def writePData(pdata, pdata_file_name, verbose=True): + if (verbose): print '*** writePData ***' + + pdata_writer = vtk.vtkPolyDataWriter() + pdata_writer.SetFileName(pdata_file_name) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + pdata_writer.SetInputData(pdata) + else: + pdata_writer.SetInput(pdata) + pdata_writer.Update() + pdata_writer.Write() diff --git a/vtk_py/writePData.pyc b/vtk_py/writePData.pyc new file mode 100644 index 0000000..4460045 Binary files /dev/null and b/vtk_py/writePData.pyc differ diff --git a/vtk_py/writeSTL.py b/vtk_py/writeSTL.py new file mode 100644 index 0000000..29d5bfa --- /dev/null +++ b/vtk_py/writeSTL.py @@ -0,0 +1,17 @@ +######################################################################## + +import vtk + +######################################################################## + +def writeSTL(stl, stl_file_name, verbose=True): + if (verbose): print '*** writeSTL ***' + + stl_writer = vtk.vtkSTLWriter() + stl_writer.SetFileName(stl_file_name) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + stl_writer.SetInputData(stl) + else: + stl_writer.SetInput(stl) + stl_writer.Update() + stl_writer.Write() diff --git a/vtk_py/writeSTL.pyc b/vtk_py/writeSTL.pyc new file mode 100644 index 0000000..152db52 Binary files /dev/null and b/vtk_py/writeSTL.pyc differ diff --git a/vtk_py/writeUGrid.py b/vtk_py/writeUGrid.py new file mode 100644 index 0000000..a1a7c0c --- /dev/null +++ b/vtk_py/writeUGrid.py @@ -0,0 +1,17 @@ +######################################################################## + +import vtk + +######################################################################## + +def writeUGrid(ugrid, ugrid_file_name, verbose=True): + if (verbose): print '*** writeUGrid ***' + + ugrid_writer = vtk.vtkUnstructuredGridWriter() + ugrid_writer.SetFileName(ugrid_file_name) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + ugrid_writer.SetInputData(ugrid) + else: + ugrid_writer.SetInput(ugrid) + ugrid_writer.Update() + ugrid_writer.Write() diff --git a/vtk_py/writeUGrid.pyc b/vtk_py/writeUGrid.pyc new file mode 100644 index 0000000..05d78cd Binary files /dev/null and b/vtk_py/writeUGrid.pyc differ diff --git a/vtk_py/writeXMLImage.py b/vtk_py/writeXMLImage.py new file mode 100644 index 0000000..75f3583 --- /dev/null +++ b/vtk_py/writeXMLImage.py @@ -0,0 +1,17 @@ +######################################################################## + +import vtk + +######################################################################## + +def writeXMLImage(image, image_file_name, verbose=True): + if (verbose): print '*** writeXMLImage ***' + + image_writer = vtk.vtkXMLImageDataWriter() + image_writer.SetFileName(image_file_name) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + image_writer.SetInputData(image) + else: + image_writer.SetInput(image) + image_writer.Update() + image_writer.Write() diff --git a/vtk_py/writeXMLImage.pyc b/vtk_py/writeXMLImage.pyc new file mode 100644 index 0000000..f19dc39 Binary files /dev/null and b/vtk_py/writeXMLImage.pyc differ diff --git a/vtk_py/writeXMLPData.pyc b/vtk_py/writeXMLPData.pyc new file mode 100644 index 0000000..f07d848 Binary files /dev/null and b/vtk_py/writeXMLPData.pyc differ diff --git a/vtk_py/writeXMLPdata.py b/vtk_py/writeXMLPdata.py new file mode 100644 index 0000000..8354f8e --- /dev/null +++ b/vtk_py/writeXMLPdata.py @@ -0,0 +1,17 @@ +######################################################################## + +import vtk + +######################################################################## + +def writeXMLPData(pdata, pdata_file_name, verbose=True): + if (verbose): print '*** writeXMLPData ***' + + pdata_writer = vtk.vtkXMLPolyDataWriter() + pdata_writer.SetFileName(pdata_file_name) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + pdata_writer.SetInputData(pdata) + else: + pdata_writer.SetInput(pdata) + pdata_writer.Update() + pdata_writer.Write() diff --git a/vtk_py/writeXMLUGrid.py b/vtk_py/writeXMLUGrid.py new file mode 100644 index 0000000..70cb8d1 --- /dev/null +++ b/vtk_py/writeXMLUGrid.py @@ -0,0 +1,18 @@ +######################################################################## + +import vtk + +######################################################################## + +def writeXMLUGrid(ugrid, ugrid_file_name, verbose=True): + + if (verbose): print '*** writeXMLUGrid ***' + + ugrid_writer = vtk.vtkXMLUnstructuredGridWriter() + ugrid_writer.SetFileName(ugrid_file_name) + if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): + ugrid_writer.SetInputData(ugrid) + else: + ugrid_writer.SetInput(ugrid) + ugrid_writer.Update() + ugrid_writer.Write() diff --git a/vtk_py/writeXMLUGrid.pyc b/vtk_py/writeXMLUGrid.pyc new file mode 100644 index 0000000..11c39c8 Binary files /dev/null and b/vtk_py/writeXMLUGrid.pyc differ