data/points and transforms

Regarding the use of transforms in Matplotlib, what

    > would be the simplest way to convert a quantity
    > expressed in data coordinates to points and conversely?

    > Are the methods gca().transData.xy_tup() and
    > inverse_xy_tup() what I'm looking for? If so, how
    > should I be calling them?

I think the easiest way is to transform the data to screen coordinates
and then apply a scale factor to convert pixels to points. All of the
transform methods

  xy_tup(xy) - transform the tuple (x,y)
  seq_x_y(x, y) - transform the python sequences x and y
  numerix_x_y(x, y) - x and y are numerix 1D arrays
  seq_xy_tups(seq) - seq is a sequence of xy tuples

return screen coords. To get points from left, bottom, you would
could convert to inches by dividing by dpi, and then multiply by the
number of points per inch. Untested, off the cuff, but should be
right:

    # display coords
    dx, dy = trans.xy_tup(x, y)

    # points from left of figure window
    px = dx/dpi*72

    # points from bottom of figure window
    py = dy/dpi*72

with the usual caveat that screen dpi is not the same in the x and y
directions so the physical units may not be exact when displayed.

JDH

John Hunter wrote:

"Dominique" == Dominique Orban <Dominique.Orban@...92...> writes:

    > Regarding the use of transforms in Matplotlib, what
    > would be the simplest way to convert a quantity
    > expressed in data coordinates to points and conversely?

    # display coords
    dx, dy = trans.xy_tup(x, y)

    # points from left of figure window
    px = dx/dpi*72

    # points from bottom of figure window
    py = dy/dpi*72

Thanks, I think I understand. The reason I ask is to be able to compute displacements in data coordinates when they are given in points.

Now I am confused by the following test (Windows XP, Matplotlib 0.71, Numeric 23.0 from the Enthought edition of Python 2.3):

···

##################
from matplotlib.pylab import *
from matplotlib import rcParams

dpi = rcParams['figure.dpi']
ppi = 72.0
ratio = ppi/dpi

ax = axes( [0.1, 0.1, 0.8, 0.8] )
trans = ax.transData

z = (0,0)
dz = trans.xy_tup( z )
ddz = ( dz[0]*ratio, dz[1]*ratio )
print str(z) + ' in data units is ' + str(ddz) + ' in screen coords'

# See how many data units in each direction is a
# displacement of 'delta' points in each direction
delta = 5
r = ( ddz[0] + delta, ddz[1] + delta) # = origin + (10, 10)
rdx, rdy = trans.inverse_xy_tup( r )
rddx = rdx/ratio
rddy = rdy/ratio
print str(r) + ' in screen coords is ' + str((rddx,rddy)) + ' in data units'
##################

This script produces:

(0, 0) in data units is (57.600000000000001, 43.200000000000003) in screen coords

(62.600000000000001, 48.200000000000003) in screen coords is (-0.0030381944444444415, 0.00057870370370370161) in data units

How is it possible that I obtain a negative number in this last tuple? Is it a numerical error or am I missing something?

A second question: I want to draw a line going from (0,0) to (1,1), but that stops short of (1,1), leaving just enough room for an object that has a radius of 5 points. Is this how I should compute how far from (1,1) the line should stop, in data coordinates?

Yes, this is related to the arrow class I mentioned in an earlier post. This is an attempt to adjust the position of the arrow head, so its tip points to, e.g., (1,1) and the stem is just long enough that it doesn't overlap with the head. I'm probably not choosing the easy way but then, I am not sure what the easy way would be.

Many thanks,
Dominique