corrections to manifest

Add pure-python integrator to verlet chain example
This commit is contained in:
Luke Campagnola 2014-12-23 15:55:52 -05:00
parent 9a951318be
commit 77906fc7a2
5 changed files with 97 additions and 30 deletions

View File

@ -1,6 +1,6 @@
recursive-include pyqtgraph *.py *.ui *.m README *.txt recursive-include pyqtgraph *.py *.ui *.m README *.txt
recursive-include tests *.py *.ui recursive-include tests *.py *.ui
recursive-include examples *.py *.ui recursive-include examples *.py *.ui *.gz *.cfg
recursive-include doc *.rst *.py *.svg *.png *.jpg recursive-include doc *.rst *.py *.svg *.png *.jpg
recursive-include doc/build/html * recursive-include doc/build/html *
recursive-include tools * recursive-include tools *

View File

@ -1,7 +1,7 @@
import pyqtgraph as pg import pyqtgraph as pg
import numpy as np import numpy as np
import time import time
from .relax import relax from . import relax
class ChainSim(pg.QtCore.QObject): class ChainSim(pg.QtCore.QObject):
@ -52,7 +52,7 @@ class ChainSim(pg.QtCore.QObject):
self.mrel1[self.fixed[l2]] = 0 self.mrel1[self.fixed[l2]] = 0
self.mrel2 = 1.0 - self.mrel1 self.mrel2 = 1.0 - self.mrel1
for i in range(100): for i in range(10):
self.relax(n=10) self.relax(n=10)
self.initialized = True self.initialized = True
@ -76,6 +76,10 @@ class ChainSim(pg.QtCore.QObject):
dt = now - self.lasttime dt = now - self.lasttime
self.lasttime = now self.lasttime = now
# limit amount of work to be done between frames
if not relax.COMPILED:
dt = self.maxTimeStep
if self.lastpos is None: if self.lastpos is None:
self.lastpos = self.pos self.lastpos = self.pos
@ -103,8 +107,9 @@ class ChainSim(pg.QtCore.QObject):
def relax(self, n=50): def relax(self, n=50):
# speed up with C magic # speed up with C magic if possible
relax(self.pos, self.links, self.mrel1, self.mrel2, self.lengths, self.push, self.pull, n) relax.relax(self.pos, self.links, self.mrel1, self.mrel2, self.lengths, self.push, self.pull, n)
self.relaxed.emit() self.relaxed.emit()

Binary file not shown.

View File

@ -2,9 +2,15 @@ import ctypes
import os import os
so = os.path.join(os.path.dirname(__file__), 'maths.so') so = os.path.join(os.path.dirname(__file__), 'maths.so')
lib = ctypes.CDLL(so) try:
lib = ctypes.CDLL(so)
COMPILED = True
except OSError:
COMPILED = False
lib.relax.argtypes = [
if COMPILED:
lib.relax.argtypes = [
ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p,
@ -16,8 +22,49 @@ lib.relax.argtypes = [
ctypes.c_int, ctypes.c_int,
] ]
def relax(pos, links, mrel1, mrel2, lengths, push, pull, iters): def relax(pos, links, mrel1, mrel2, lengths, push, pull, iters):
nlinks = links.shape[0] nlinks = links.shape[0]
lib.relax(pos.ctypes, links.ctypes, mrel1.ctypes, mrel2.ctypes, lengths.ctypes, push.ctypes, pull.ctypes, nlinks, iters) lib.relax(pos.ctypes, links.ctypes, mrel1.ctypes, mrel2.ctypes, lengths.ctypes, push.ctypes, pull.ctypes, nlinks, iters)
else:
def relax(pos, links, mrel1, mrel2, lengths, push, pull, iters):
lengths2 = lengths**2
for i in range(iters):
#p1 = links[:, 0]
#p2 = links[:, 1]
#x1 = pos[p1]
#x2 = pos[p2]
#dx = x2 - x1
#dist = (dx**2).sum(axis=1)**0.5
#mask = (npush & (dist < lengths)) | (npull & (dist > lengths))
##dist[mask] = lengths[mask]
#change = (lengths-dist) / dist
#change[mask] = 0
#dx *= change[:, np.newaxis]
#print dx
##pos[p1] -= mrel2 * dx
##pos[p2] += mrel1 * dx
#for j in range(links.shape[0]):
#pos[links[j,0]] -= mrel2[j] * dx[j]
#pos[links[j,1]] += mrel1[j] * dx[j]
for l in range(links.shape[0]):
p1, p2 = links[l];
x1 = pos[p1]
x2 = pos[p2]
dx = x2 - x1
dist2 = (dx**2).sum()
if (push[l] and dist2 < lengths2[l]) or (pull[l] and dist2 > lengths2[l]):
dist = dist2 ** 0.5
change = (lengths[l]-dist) / dist
dx *= change
pos[p1] -= mrel2[l] * dx
pos[p2] += mrel1[l] * dx

View File

@ -1,26 +1,38 @@
""" """
Mechanical simulation of a chain using verlet integration. Mechanical simulation of a chain using verlet integration.
Use the mouse to interact with one of the chains.
By default, this uses a slow, pure-python integrator to solve the chain link
positions. Unix users may compile a small math library to speed this up by
running the `examples/verlet_chain/make` script.
""" """
import initExample ## Add path to library (just for examples; you do not need this) import initExample ## Add path to library (just for examples; you do not need this)
import pyqtgraph as pg import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui from pyqtgraph.Qt import QtCore, QtGui
import numpy as np import numpy as np
from verlet_chain import ChainSim import verlet_chain
sim = ChainSim() sim = verlet_chain.ChainSim()
if verlet_chain.relax.COMPILED:
# Use more complex chain if compiled mad library is available.
chlen1 = 80
chlen2 = 60
linklen = 1
else:
chlen1 = 10
chlen2 = 8
linklen = 8
chlen1 = 80
chlen2 = 60
npts = chlen1 + chlen2 npts = chlen1 + chlen2
sim.mass = np.ones(npts) sim.mass = np.ones(npts)
sim.mass[chlen1-15] = 100 sim.mass[int(chlen1 * 0.8)] = 100
sim.mass[chlen1-1] = 500 sim.mass[chlen1-1] = 500
sim.mass[npts-1] = 200 sim.mass[npts-1] = 200
@ -31,8 +43,10 @@ sim.fixed[chlen1] = True
sim.pos = np.empty((npts, 2)) sim.pos = np.empty((npts, 2))
sim.pos[:chlen1, 0] = 0 sim.pos[:chlen1, 0] = 0
sim.pos[chlen1:, 0] = 10 sim.pos[chlen1:, 0] = 10
sim.pos[:chlen1, 1] = np.arange(chlen1) sim.pos[:chlen1, 1] = np.arange(chlen1) * linklen
sim.pos[chlen1:, 1] = np.arange(chlen2) sim.pos[chlen1:, 1] = np.arange(chlen2) * linklen
# to prevent miraculous balancing acts:
sim.pos += np.random.normal(size=sim.pos.shape, scale=1e-3)
links1 = [(j, i+j+1) for i in range(chlen1) for j in range(chlen1-i-1)] links1 = [(j, i+j+1) for i in range(chlen1) for j in range(chlen1-i-1)]
links2 = [(j, i+j+1) for i in range(chlen2) for j in range(chlen2-i-1)] links2 = [(j, i+j+1) for i in range(chlen2) for j in range(chlen2-i-1)]
@ -55,7 +69,8 @@ sim.push = np.concatenate([push1, push2, np.array([True], dtype=bool)])
sim.pull = np.ones(sim.links.shape[0], dtype=bool) sim.pull = np.ones(sim.links.shape[0], dtype=bool)
sim.pull[-1] = False sim.pull[-1] = False
mousepos = sim.pos[0] # move chain initially just to generate some motion if the mouse is not over the window
mousepos = np.array([30, 20])
def display(): def display():