From: Andrew P <gr...@gm...> - 2005-09-28 05:19:38
|
Hi Alex, Let me explain a little more what I'm trying to do. First off. here is a screenshot of what I did today: http://www.stefanscott.com/ca_example.jpg That is a 500x400 cellular automata, and a little cramped. What I'd like to do is have it scroll, and this is why I was asking about the best way to draw my numpy array. Optimizing is one thing, not being stupid because you don't know how to draw to the canvas properly is another :) I just found this java example of what I'm trying to do, picture worth a thousand words and all that: http://math.hws.edu/xJava/CA/ Right now I convert to a point list and draw, which is really slow. For instance, with my array code below, I get: >>> timeIt(10) 1.1327484359 Which I am happy with. My original non-numpy code was 20x slower :) That's ten calculations of a 1000x1000 CA, which is more the size I am shooting for. I have a point, I promise.. Lets say I want a scrolling speed of 2 seconds a screen, gives me 2 seconds to calculate 1000 lines, so back of the napkin puts me at about .15 seconds to calculate 1000 lines on my machine, which is much less than 2 seconds, and is great for my 1ghz Apple iBook even. So far so good. But then I try timing the conversion of my array to a point list: >>> a =3D do_ca(1000,1000,90) >>> def timePL(num): ... res =3D [] ... t1 =3D time.clock() ... for i in range(num): ... for i in range(1000): ... [res.append([x,i]) for x in nonzero(a[i])] ... res =3D [] ... t2 =3D time.clock() ... print t2 - t1 ... >>> timePL(10) 1.06879561509 It takes me 1/10th of a second just to convert my numpy array to a point list! Which puts me at 100 seconds if I wanted to scroll a full screen one line at a time. More realistically, the scrolling would probably take place at maybe 25 fps, or so. But that would still be 40 redraws, or 4 seconds at full steam ahead on my fairly fast and modern computer, let alone my poor iBook. I have to reiterate this is my first GUI app ever, and it's amazing what I've done just today in my first day of Pythoncard. But I'm definitely not trying for speed for the sake of speed. I just need to know how to do it right. I'd like to draw it as it calculates, and have it scroll when it reaches the bottom. Popping off the first row of my array and calculating the next bottom row is practically instant in numpy, but then I'm stuck wit= h that slow iteration over each element. Which is why I was wondering if ther= e was a way to draw the array directly, without an RGB or point list conversion inbetween. I don't even think I can cache the points list, since I'd still have to interate over it to do +1 to the row coordinates. Which may be faster, but still feels like I'm polishing a turd :) Am I missing something really obvious? Here is my benchmarking code: from Numeric import * import time # the numpy bit is messy, but the fastest i could come up with: # 3 element window, 4*row+2*row+row, to make integers from # 3 bit binaries. 1<< converts to 8 bit place, # &rule checks rule number for membership, # not_equal changes any number !=3D to zero to 1 def do_ca(w,h,rule): # make zeros array,set a[0] middle element to 1 to seed a =3D zeros((h,w)) a[0,w/2] =3D 1 res =3D [] for i in range(h-1): r =3D a[i] r2 =3D a[i+1] not_equal((1<<(4*r[:-2]+2*r[1:-1]+r[2:])&rule),0, r2[1:-1]) not_equal((1<<(4*r[-1]+2*r[0]+r[1])&rule),0, r2[0:0]) not_equal((1<<(4*r[-2]+2*r[1]+r[0])&rule),0, r2[-1:]) # uncomment next line and return res to get list for # drawPointList(res): # [res.append([x,i]) for x in nonzero(r2)] return a def timeIt(num): t1 =3D time.clock() for i in range(num): do_ca(1000,1000,90) t2 =3D time.clock() print t2 - t1 |