On 11/11/2015 at 05:50, xxxxxxxx wrote:
Hello all,
I am using numpy for array calculations on a c4d.pointobject. The manipulations within numpy are super fast, but it turns out that converting to and from c4d.Vectors is a real bottleneck. Since this is an essential step when using numpy, I was hoping that someone else has already found a good solution for it?
The fastest code I could come up with is attached below. Having a look at the execution times is interesting, because it shows that the internal getting and setting of vectors is much faster than the conversion to and from numpy of those vector objects.
c4d.GetAllPoints: 0.073354
list2np : 0.455179
np manipulation: 0.067916
np2list : 0.439967
c4d.SetAllPoints : 0.030023
Does anybody have suggestions as to further speed up this code? Especially the np2list function is critical, since it has to be called every frame (when used in a generator). I am open to exotic solutions such as cython, numba or whatever, as long as I can get it working on my machine.
Your help is really appreciated!
regards,
Hermen
code to be run from a script with a point object selected
import c4d
from c4d import Vector
import numpy as np
#import c4d2numpy as npc
import time
now = time.clock
Vec = Vector
y & z are reversed because of left-handed system in cinema 4d
def ipts(pts) :
for p in pts:
yield p.x
yield p.z
yield p.y
def tprint(tl) :
t0 = [t[0] for t in tl]
s0 = [t[1] for t in tl]
print ' '
for i,t in enumerate(t0) :
if i==0: continue
print s0 _, t-t0[i-1]
def list2np(lst) :
A = np.fromiter(ipts(lst), dtype=np.float, count=3*len(lst))
return A.reshape((len(lst), 3))
def np2list(A) :
return map(Vec, A[:,0], A[:,2], A[:,1])
def main() :
op.ResizeObject(1000000)
t = []
t.append( (now(), 'start' ) )
pts = op.GetAllPoints()
t.append( (now(), 'c4d.GetAllPoints:' ) )
A = list2np(pts)
t.append( (now(), 'list2np :' ) )
#print A.shape
B = A + 10. * np.random.random((A.shape))
t.append( (now(), 'np manipulation:' ) )
pts = np2list(B)
#print len(pts)
t.append( (now(), 'np2list :' ) )
op.SetAllPoints(pts)
op.Message(c4d.MSG_UPDATE)
t.append( (now(), 'c4d.SetAllPoints:' ) )
op.SetAllPoints(pts)
op.Message(c4d.MSG_UPDATE)
tprint(t)
if __name__=='__main__':
main()