New backend API

I think there are two issues here. The postscript

    > interpreter doesnt like to stroke long paths. If I break
    > the path into 50 point chunks instead of 1000 point
    > chunks, I see an improvement.

That's odd, because we never saw an issue stroking long pats before.
Or at least noone has ever reported it.

    > Also, if I do the transform in backend_ps, instead of
    > passing it to the postscript interpreter, I see a big
    > speedup at render time. Right now I am doing this
    > transform by hand:

    > a,b,c,d,tx,ty=vec6 xo = a*x+c*y +tx yo = b*x+d*y + ty x,y
    > = xo,yo

    > Is there a better way to do this? I thought I could simply
    > call numerix_x_y, but that function is not compatible with
    > nonlinear transforms (returns a domain error if one of the
    > axes is log-scaled).

You can transform the xy values point by point. Instead of separating
them into their nonlinear and affine components as we are currently
doing in backend_ps, you can call trans.xy_tup which will do both. If
successful, it will return the transformed xy, if it fails, it will
raise a ValueError, and you can set the moveto/lineto state
accordingly.

But I am still confused by your previous post: you said that when you
tried to load the simple plot example PS file in gs, the line rendered
quickly, and then there was the interminable pause. This suggests
that it is not the transformation in gs that is the bottleneck, but
something that happens after it.

In any case, here is an example script creating a semilogx transform.
The first transformation succeeds, the second raises a ValueError

from matplotlib.transforms import SeparableTransformation, \
     Point, Value, Bbox, LOG10, IDENTITY, Func
import matplotlib.numerix as nx

# make some random bbox transforms
def rand_point():
    x,y = nx.mlab.rand(2)
    return Point( Value(x), Value(y) )

def rand_bbox():
    ll = rand_point()
    ur = rand_point()
    return Bbox(ll, ur)

b1 = rand_bbox()
b2 = rand_bbox()
funcx = Func(LOG10)
funcy = Func(IDENTITY)

# semilogx
trans = SeparableTransformation(b1, b2, funcx, funcy)

print trans.xy_tup((1,2)) #ok
print trans.xy_tup((-1,2)) #raises

Hi John,

    > I think there are two issues here. The postscript
    > interpreter doesnt like to stroke long paths. If I break
    > the path into 50 point chunks instead of 1000 point
    > chunks, I see an improvement.

That's odd, because we never saw an issue stroking long pats before.
Or at least noone has ever reported it.

I suppose it could be an issue with my gs, a few weeks ago I upgraded to
gcc-4.1 and have since recompiled gs. Would you run this script:

from pylab import *
x=rand(1000)
y=rand(1000)
plot(x,y)
savefig('apitest.eps')

and then open the file in ggv? If it opens quickly, maybe you could also try
rand(10000).

    > Also, if I do the transform in backend_ps, instead of
    > passing it to the postscript interpreter, I see a big
    > speedup at render time. Right now I am doing this
    > transform by hand:

    > a,b,c,d,tx,ty=vec6 xo = a*x+c*y +tx yo = b*x+d*y + ty x,y
    > = xo,yo

    > Is there a better way to do this? I thought I could simply
    > call numerix_x_y, but that function is not compatible with
    > nonlinear transforms (returns a domain error if one of the
    > axes is log-scaled).

You can transform the xy values point by point. Instead of separating
them into their nonlinear and affine components as we are currently
doing in backend_ps, you can call trans.xy_tup which will do both. If
successful, it will return the transformed xy, if it fails, it will
raise a ValueError, and you can set the moveto/lineto state
accordingly.

I see. But can that be done in a list comprehension? I think it will require a
regular for loop. I think doing the transforms as I described above is a
better solution. It fixed the render times on my machine and my
backend_driver tests looked fine. I'll wait for feedback, and test a little
more tomorrow before committing.

But I am still confused by your previous post: you said that when you
tried to load the simple plot example PS file in gs, the line rendered
quickly, and then there was the interminable pause. This suggests
that it is not the transformation in gs that is the bottleneck, but
something that happens after it.

It was axes_demo.py. I discovered the reason: a 10,000 pt line is written to
the postscript file, but only 1000 points are drawn because of the x-axis
limits. So it was churning away, processing points that dont get drawn. I
confirmed this was the case: by commenting out the other 9000 points in
axes_demo_PS.ps, the render time improved.

Darren

···

On Monday 03 April 2006 10:16 pm, you wrote:

Darren,

I suppose it could be an issue with my gs, a few weeks ago I upgraded to gcc-4.1 and have since recompiled gs. Would you run this script:

from pylab import *
x=rand(1000)
y=rand(1000)
plot(x,y)
savefig('apitest.eps')

and then open the file in ggv? If it opens quickly, maybe you could also try rand(10000).

About 25 seconds on a 1.6G Pentium M, ESP Ghostscript 8.15.1 (2005-09-22)

Eric

I see a draw_lines_testing in backend_ps. I think it could be a good approach,
but it doesnt make it very easy to skip unplottable elements like nans, infs.
Could xy_tup accept a kwarg to make it raise an error when it tries to
transform an inf or a nan?

Darren

···

On Monday 03 April 2006 22:16, John Hunter wrote:

    > Also, if I do the transform in backend_ps, instead of
    > passing it to the postscript interpreter, I see a big
    > speedup at render time. Right now I am doing this
    > transform by hand:

    > a,b,c,d,tx,ty=vec6 xo = a*x+c*y +tx yo = b*x+d*y + ty x,y
    > = xo,yo

    > Is there a better way to do this? I thought I could simply
    > call numerix_x_y, but that function is not compatible with
    > nonlinear transforms (returns a domain error if one of the
    > axes is log-scaled).

You can transform the xy values point by point. Instead of separating
them into their nonlinear and affine components as we are currently
doing in backend_ps, you can call trans.xy_tup which will do both. If
successful, it will return the transformed xy, if it fails, it will
raise a ValueError, and you can set the moveto/lineto state
accordingly.