Skip to content

Commit

Permalink
3.3
Browse files Browse the repository at this point in the history
  • Loading branch information
marcomusy committed Jun 11, 2019
1 parent 16b5efc commit 202bd10
Show file tree
Hide file tree
Showing 45 changed files with 713 additions and 396 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ python tutorial.py


## References

- M. Musy, G. Dalmasso, J. Sharpe and N. Sime, "`vtkplotter`*: plotting in FEniCS with python*", ([link](https://github.com/marcomusy/vtkplotter/blob/master/docs/fenics_poster.pdf)).
Poster at the [FEniCS'2019](https://fenicsproject.org/fenics19/) Conference,
Carnegie Institution for Science Department of Terrestrial Magnetism, Washington DC, June 2019.

- G. Dalmasso, *"Evolution in space and time of 3D volumetric images"*. Talk at the Conference for [Image-based Modeling and Simulation of Morphogenesis](https://www.pks.mpg.de/imsm19/).
Max Planck Institute for the Physics of Complex Systems, Dresden, Germany, March 2019.


Scientific publications using `vtkplotter` so far:

1. X. Diego _et al._:
Expand Down
41 changes: 16 additions & 25 deletions bin/vtkconvert
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ from vtkplotter.utils import humansort
from vtkplotter import printc
import sys, argparse

allowedexts = ['vtk', 'vtp', 'vtu', 'vts', 'ply', 'stl', 'byu', 'xml']
allowedexts = ['vtk', 'vtp', 'vtu', 'vts', 'ply', 'stl', 'byu', 'xml', 'vti','tif','mhd','xml']

pr = argparse.ArgumentParser(description="Allowed targets: "+str(allowedexts))
pr.add_argument('files', nargs='*', help="Input filename(s)")
pr.add_argument("-n", "--normalize", help="normalize target size", action="store_true")
pr.add_argument("-c", "--clean", help="remove coincident points", action="store_true")
pr.add_argument("-m", "--mirror", help="mirror along the x-axis", action="store_true")
pr.add_argument("-b", "--binary", help="whether output is binary or not", action="store_true")
pr.add_argument("-t", "--triangle", help="Convert polygons to triangles", action="store_true")
pr.add_argument("-to", type=str, help="target format [vtk]", default='vtk', metavar='')
args = pr.parse_args()

Expand All @@ -30,30 +35,16 @@ for f in args.files:
if target_ext == source_ext:
continue

if source_ext=='wrl':
import vtk

importer = vtk.vtkVRMLImporter()
importer.SetFileName(f)
importer.Read()
importer.Update()

actors = importer.GetRenderer().GetActors() #vtkActorCollection
actors.InitTraversal()

polyapp = vtk.vtkAppendPolyData()
for i in range(actors.GetNumberOfItems()):
act = actors.GetNextActor()
poly = act.clean().computeNormals().polydata(False)
polyapp.AddInputData(poly)
print('merging polydata',i ,'with', poly.GetNumberOfPoints(),'points')
polyapp.Update()
poly = polyapp.GetOutput()
else:
a = load(f)
poly = a.polydata(False)
a = load(f)
if args.normalize:
a.normalize()
if args.triangle:
a.triangle()
if args.clean:
a.clean()
if args.mirror:
a.mirror()

newf = f.replace("."+source_ext,"")+"."+target_ext
printc('converting',f, '->', newf, c='g')
write(poly, newf)
write(a, newf, binary=args.binary)

Binary file added docs/fenics_poster.pdf
Binary file not shown.
8 changes: 4 additions & 4 deletions examples/advanced/convexHull.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2df3bd9babbd4920930a7abb9a38d432",
"model_id": "5285de33fccc4d3aaae6e58bc6073e63",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Plot(antialias=3, axes=['x', 'y', 'z'], background_color=16777215, fps_meter=False, grid=[-1, -1, -1, 1, 1, 1]"
"Plot(antialias=3, axes=['x', 'y', 'z'], background_color=16777215, camera=[4.5, 4.5, 4.5, 0.0, 0.0, 0.0, 1.0, "
]
},
"metadata": {},
Expand All @@ -27,7 +27,7 @@
"\n",
"scalars = spid.coordinates()[:,2] # take the z coordinates of vertices as scalars\n",
"\n",
"spid.pointColors(scalars, cmap='afmhot_r') # use the scalar to color the mesh\n",
"spid.pointColors(scalars, cmap='afmhot_r') # use those scalar to color the mesh\n",
"\n",
"chull = convexHull(spid).c(\"black\").alpha(0.2).wireframe()\n",
"\n",
Expand Down Expand Up @@ -58,7 +58,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
"version": "3.6.7"
}
},
"nbformat": 4,
Expand Down
99 changes: 99 additions & 0 deletions examples/advanced/thinplate_morphing_2d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"""Take 2 clouds of points, source and target, and morph
source on target using thin plate splines as a model.
The fitting minimizes the distance to the target surface
using algorithms available in the scipy.optimize package."""
from vtkplotter import *
import scipy.optimize as opt
import numpy as np
np.random.seed(0)

class Morpher:
def __init__(self):
self.source = None
self.morphed_source = None
self.target = None
self.bound = None
self.method = "SLSQP" # 'SLSQP', 'L-BFGS-B', 'TNC' ...
self.fitTolerance = 1e-6
self.params = []
self.fitResult = None
self.chi2 = 1.0e30
self.ndf = None
self.ptsource = []
self.pttarget = []

def _func(self, pars):
self.params = np.array(pars)

ptmoved = np.multiply((self.pttarget-self.ptsource).T, (1+self.params)).T + self.ptsource
self.morphed_source = thinPlateSpline(self.source, self.ptsource, ptmoved)

d = self.morphed_source.getPoints() - self.target.getPoints()
chi2 = np.sum(np.multiply(d,d))/self.ndf
if chi2 < self.chi2:
print("Emin ->", chi2)
self.chi2 = chi2
return chi2

# ------------------------------------------------------- Fit
def morph(self):

print("\n..minimizing with " + self.method)
self.morphed_source = self.source.clone()

indexes = list(range(0,self.source.N(), int(self.source.N()/self.ndf)))
self.ptsource = self.source.getPoints()[indexes]
self.pttarget = self.target.getPoints()[indexes]
self.ndf = len(indexes)

bnds = [(-self.bound, self.bound)] * self.ndf
x0 = [0.0] * self.ndf # initial guess
res = opt.minimize(self._func, x0,
bounds=bnds,
method=self.method,
tol=self.fitTolerance)
# recalc for all pts:
self._func(res["x"])
print("\nFinal fit score", res["fun"])
self.fitResult = res

# ------------------------------------------------------- Visualization
def draw_shapes(self):
sb = self.source.bounds()
x1, x2, y1, y2, z1, z2 = sb
maxb = max(x2-x1, y2-y1)
grid0 = Grid(self.source.centerOfMass(), sx=maxb, sy=maxb, resx=40, resy=40)
T = self.morphed_source.getTransform()
grid1 = grid0.alpha(0.3).clone().transformMesh(T) # warp the grid

text1 = Text(__doc__, c="k")
text2 = Text("morphed vs target\nn.d.f.="+str(self.ndf), c="k")
arrows = Arrows(self.ptsource, self.pttarget, c='gray', alpha=0.5, s=1)

self.morphed_source.pointSize(10).c('g')
show(grid0, self.source, self.target, arrows, text1, at=0, N=2, bg="w", axes=0)
show(grid1, self.morphed_source, self.target, text2, at=1, zoom=1.2, interactive=1)


#################################
if __name__ == "__main__":

mr = Morpher()

# make up a random cloud and distort it
pts_s = np.random.randn(100, 3)
pts_t = np.array(pts_s) +np.sin(2*pts_s)/5
pts_s[:,2] = 0 # let's make it 2D
pts_t[:,2] = 0

mr.source = Points(pts_s, r=10, c="g", alpha=1)
mr.target = Points(pts_t, r=10, c="r", alpha=1).rotateZ(10) # add rotation too

mr.bound = 1 # limits the parameter value
mr.ndf = 10 # fit degree (nr of degrees of freedom)

mr.morph()

#print("Result of parameter fit:\n", mr.params)
#now mr.msource contains the modified/morphed source.
mr.draw_shapes()
8 changes: 4 additions & 4 deletions examples/basic/acollection.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "0099fa72ab0841b4a7b1b4885ee63502",
"model_id": "2f6ae0f7e52e4127b293aabac95456b9",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Plot(antialias=True, axes=['x', 'y', 'z'], background_color=16777215, fps_meter=False, grid=[-1, -1, -1, 1, 1,"
"Plot(antialias=3, axes=['x', 'y', 'z'], background_color=16777215, camera=[4.5, 4.5, 4.5, 0.0, 0.0, 0.0, 1.0, "
]
},
"metadata": {},
Expand All @@ -24,7 +24,7 @@
"from vtkplotter import *\n",
"\n",
"for i in range(10):\n",
" Cone(pos=[3*i, 0, 0], axis=[i, i-5, 0]) # no variable assigned\n",
" Cone(pos=[3*i, 0, 0], axis=[i, i-5, 0]) # no variable needs to be assigned\n",
"\n",
"# collection() retrieves the list of all sofar created actors\n",
"show(collection())"
Expand Down Expand Up @@ -54,7 +54,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
"version": "3.6.7"
}
},
"nbformat": 4,
Expand Down
6 changes: 3 additions & 3 deletions examples/basic/align1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
"text": [
"\u001b[1m\u001b[32mave. squared distance = 51.376919095994744\u001b[0m\n",
"\u001b[1mvtkTransform is available with getTransform():\u001b[0m\n",
"\u001b[1m[(vtkCommonTransformsPython.vtkLandmarkTransform)0x7f422e0bc9a8]\u001b[0m\n"
"\u001b[1m[(vtkCommonTransformsPython.vtkLandmarkTransform)0x1221b4468]\u001b[0m\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "3ca3fece6ed3409db046f23893d55138",
"model_id": "5190919d89e84217874f7b782f20a34b",
"version_major": 2,
"version_minor": 0
},
Expand Down Expand Up @@ -86,7 +86,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
"version": "3.7.1"
}
},
"nbformat": 4,
Expand Down
21 changes: 9 additions & 12 deletions examples/basic/align2.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
"cells": [
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "0bd752352d564b6eaa75d02643be1031",
"model_id": "88a4f272aa0b44bc9b9dd0b9d1bace40",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Plot(antialias=3, axes=['x', 'y', 'z'], background_color=16777215, fps_meter=False, grid=[-1, -1, -1, 1, 1, 1]"
"Plot(antialias=3, axes=['x', 'y', 'z'], background_color=16777215, camera=[4.5, 4.5, 4.5, 0.0, 0.0, 0.0, 1.0, "
]
},
"metadata": {},
Expand All @@ -30,7 +30,7 @@
"from random import uniform as u\n",
"from vtkplotter import *\n",
"\n",
"vp = Plotter()\n",
"vp = Plotter() # create the Plotter instance explicitly\n",
"\n",
"N1 = 15 # number of points of first set\n",
"N2 = 15 # number of points of second set\n",
Expand All @@ -39,21 +39,18 @@
"pts1 = [(u(0, x), u(0, x), u(0, x) + i) for i in range(N1)]\n",
"pts2 = [(u(0, x) + 3, u(0, x) + i / 2 + 2, u(0, x) + i + 1) for i in range(N2)]\n",
"\n",
"act1 = Points(pts1, r=6, c=\"b\").legend(\"source\")\n",
"act2 = Points(pts2, r=6, c=\"r\").legend(\"target\")\n",
"act1 = Points(pts1, c=\"b\")\n",
"act2 = Points(pts2, c=\"r\")\n",
"vp += [act1, act2]\n",
"\n",
"# find best alignment between the 2 sets of Points, e.i. find\n",
"# how to move act1 to best match act2\n",
"alpts1 = alignICP(act1, act2).coordinates()\n",
"\n",
"for i in range(N1): # draw arrows to see where points end up\n",
" vp += Arrow(pts1[i], alpts1[i], c=\"k\", alpha=0.1)\n",
" vp += Arrow(pts1[i], alpts1[i], s=0.01, c=\"k\", alpha=0.2)\n",
"\n",
"vp += Points(alpts1, r=6, c=\"b\")\n",
"\n",
"for i in range(N1): # draw arrows to see where points end up\n",
" vp += Arrow(pts1[i], alpts1[i], c=\"k\", alpha=0.1)\n",
"vp += Points(alpts1, c=\"b\")\n",
"\n",
"vp.show()"
]
Expand Down Expand Up @@ -82,7 +79,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
"version": "3.6.7"
}
},
"nbformat": 4,
Expand Down
12 changes: 6 additions & 6 deletions examples/basic/buildmesh.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 1,
"metadata": {},
"outputs": [
{
Expand All @@ -16,12 +16,12 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "435af1c389274b479abbf3f3db5984a8",
"model_id": "01ba9f20b73e4d969b5fdf268ea9d1a5",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Plot(antialias=3, axes=['x', 'y', 'z'], background_color=16777215, fps_meter=False, grid=[-1, -1, -1, 1, 1, 1]"
"Plot(antialias=3, axes=['x', 'y', 'z'], background_color=16777215, camera=[4.5, 4.5, 4.5, 0.0, 0.0, 0.0, 1.0, "
]
},
"metadata": {},
Expand All @@ -41,8 +41,8 @@
"\n",
"# the way vertices are assembled into polygons can be retrieved\n",
"# in two different formats:\n",
"printc('getCells() is :', a.getCells())\n",
"printc('getConnectivity() is:', a.getConnectivity())\n",
"printc('getCells() output :', a.getCells())\n",
"printc('getConnectivity() output:', a.getConnectivity())\n",
"\n",
"a.show()"
]
Expand Down Expand Up @@ -71,7 +71,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
"version": "3.6.7"
}
},
"nbformat": 4,
Expand Down
Loading

0 comments on commit 202bd10

Please sign in to comment.