converting data between axis [0, 1] and data coordinates [min data, max data]

Hello all,

I believe it is an easy thing to do but I haven’t figured out how to convert between coordinate systems using transData or transAxes. Here is the simple_plot.py

import numpy
import pylab

x = numpy.arange(0.0, 1.0+0.01, 0.01)
y = numpy.cos(22numpy.pi*x)
pylab.plot(x, y)

Here I want to transform y1 to axis scale between 0 and 1.
Also, I want to transform axis scale, say 0.25, to a corresponding y value in the data coordinates.

pylab.show()

Currently I am doing it manually scaling things with axis limits, etc. I believe the neat thing is to use the transforms api. Can somebody explain me how it is done with transforms? I am using 0.98.1.

Thanks in advance,

Nihat

Hello all,

I believe it is an easy thing to do but I haven’t figured out how to convert between coordinate systems using transData or transAxes.

x = numpy.arange(0.0, 1.0+0.01, 0.01)

y = numpy.cos(22numpy.pi*x)
pylab.plot(x, y)

I want to transform y1 to axis scale between 0 and 1.
Also, I want to transform a value in axis scale, say 0.25, to a corresponding y value in the data coordinates.

I used

ax = gca()
(x_screen, y_screen) = ax.transData.transform([x[10], y[10])
(x10, y10) = ax.transAxes.inverted().transform([x_screen, y_screen])

Is it the proper way of doing it? Where can I find more info on transformations in general?

Currently I am doing it manually scaling things with axis limits, etc. I believe the neat thing is to use the transforms. Can somebody explain me how it is done with transforms? I am using v0.98.1.

Thanks in advance,

Nihat

ax = gca()
(x_screen, y_screen) = ax.transData.transform([x[10], y[10])
(x10, y10) = ax.transAxes.inverted().transform([x_screen, y_screen])

Is it the proper way of doing it? Where can I find more info on transformations in general?

I'd really be interested to know the answer to this question, too. I recently wanted to do this exact same transformation. When I tried

>>> (x10, y10) = ax.transLimits.transform([x[10], y[10])

I got the desired input for *linear* data. Looking looking at the definitions of the axes transforms in the code (Axes class in axes.py) you see that:

>>> self.transData = self.transScale + (self.transLimits + self.transAxes)

where `self` is the Axes object. It would seem that your sequence of operations (`transData.transform` followed by `transAxes.inverted().transform`) should be equivalent to:

>>> transDesired = self.transScale + self.transLimits

But, when I tried using this transform, I didn't get the desired transformation for logarithmic data.

Any transform experts out there?

-Tony

···

On Jun 30, 2008, at 10:22 AM, Nihat wrote:

Nihat wrote:

Hello all,

I believe it is an easy thing to do but I haven't figured out how to convert between coordinate systems using transData or transAxes.

x = numpy.arange(0.0, 1.0+0.01, 0.01)
y = numpy.cos(2*2*numpy.pi*x)
pylab.plot(x, y)

I want to transform y1 to axis scale between 0 and 1.
Also, I want to transform a value in axis scale, say 0.25, to a corresponding y value in the data coordinates.

I used

ax = gca()
(x_screen, y_screen) = ax.transData.transform([x[10], y[10])
(x10, y10) = ax.transAxes.inverted().transform([x_screen, y_screen])

Is it the proper way of doing it? Where can I find more info on transformations in general?

The new transformations infrastructure is documented in the new docs (which are still in progress...)

   http://matplotlib.sourceforge.net/doc/html/devel/transformations.html

This document, however, doesn't describe what things like transData and transAxes are defined to be. That would probably be a useful thing to document.

transAxes places the axes within the figure.

transData maps from the data's coordinates all the way to the figure space which is (0, 0) to (1, 1). transData is a composite of the scale (for eg. logarithm), the limits (the currently "zoomed" in portion of the data), and the transAxes. It's the "fast lane" between the data and the screen.

In your example, if you expect to go between data and screen coordinates, you would do:

(x_screen, y_screen) = ax.transData.transform([x[10], y[10])
(x10, y10) = ax.transData.inverted().transform([x_screen, y_screen])

Note, we use transData both ways.

Currently I am doing it manually scaling things with axis limits, etc. I believe the neat thing is to use the transforms. Can somebody explain me how it is done with transforms? I am using v0.98.1.

I hope that answers your question, but it's not entirely clear what you would like to do. Please ask further if the above didn't help.

Cheers,
Mike

Tony S Yu wrote:

  

ax = gca()
(x_screen, y_screen) = ax.transData.transform([x[10], y[10])
(x10, y10) = ax.transAxes.inverted().transform([x_screen, y_screen])

Is it the proper way of doing it? Where can I find more info on transformations in general?
    
I'd really be interested to know the answer to this question, too. I recently wanted to do this exact same transformation. When I tried

>>> (x10, y10) = ax.transLimits.transform([x[10], y[10])

I got the desired input for *linear* data. Looking looking at the definitions of the axes transforms in the code (Axes class in axes.py) you see that:

>>> self.transData = self.transScale + (self.transLimits + self.transAxes)

where `self` is the Axes object. It would seem that your sequence of operations (`transData.transform` followed by `transAxes.inverted().transform`) should be equivalent to:

>>> transDesired = self.transScale + self.transLimits

But, when I tried using this transform, I didn't get the desired transformation for logarithmic data.

Any transform experts out there?
  

transScale is where all of the (optionally) logarithmic transformation takes place. I'm surprised

>>> transDesired = self.transScale + self.transLimits

didn't work for going from data to a (0, 0) - (1, 1) bounding box. Can you provide a small, yet complete, example that illustrates the bug so I can look at it further?

Cheers,
Mike

···

On Jun 30, 2008, at 10:22 AM, Nihat wrote:

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

I tried to put together a simple example showing my problem, but the example worked properly! Doh!

It turns out that my problem was specific to using a bounding box as an input to transform:

···

On Jun 30, 2008, at 11:13 AM, Michael Droettboom wrote:

transScale is where all of the (optionally) logarithmic transformation takes place. I’m surprised

transDesired = self.transScale + self.transLimits

didn’t work for going from data to a (0, 0) - (1, 1) bounding box. Can you provide a small, yet complete, example that illustrates the bug so I can look at it further?

=========

from numpy.random import rand

import matplotlib.pyplot as plt

ax = plt.subplot(111)

xy = rand(5,2)

ax.loglog(xy[:, 0], xy[:, 1], ‘ro’)

trans = ax.transScale + ax.transLimits

result = trans.transform(ax.dataLim)

=========

The above command gives me:

** TypeError:** ‘Bbox’ object is unsubscriptable

(Note, if I call plot instead of loglog I don’t have problems). The quick solution is to replace the last line with

result = trans.transform(ax.dataLim._points)

I guess I was confused because the transform worked fine with plot. Is the TypeError above expected behavior?

Thanks for your help.

-Tony

Tony S Yu wrote:

transScale is where all of the (optionally) logarithmic transformation takes place. I'm surprised

>>> transDesired = self.transScale + self.transLimits

didn't work for going from data to a (0, 0) - (1, 1) bounding box. Can you provide a small, yet complete, example that illustrates the bug so I can look at it further?

I tried to put together a simple example showing my problem, but the example worked properly! Doh!

It turns out that my problem was specific to using a bounding box as an input to transform:

=========
from numpy.random import rand
import matplotlib.pyplot as plt

ax = plt.subplot(111)
xy = rand(5,2)
ax.loglog(xy[:, 0], xy[:, 1], 'ro')

trans = ax.transScale + ax.transLimits
result = trans.transform(ax.dataLim) =========

The above command gives me:
* TypeError:* 'Bbox' object is unsubscriptable
(Note, if I call `plot` instead of `loglog` I don't have problems). The quick solution is to replace the last line with

>>> result = trans.transform(ax.dataLim._points)

I guess I was confused because the transform worked fine with `plot`. Is the TypeError above expected behavior?

Yes. The "transform" method is meant to take an Nx2 array, it doesn't take a bounding box. I think it probably works with non-log plots only by accident because bounding boxes can cast to arrays in some cases. It may be worth taking that out to avoid confusion, but I'll have to think on it some.

Thanks for looking into this!

Mike

···

On Jun 30, 2008, at 11:13 AM, Michael Droettboom wrote:

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

Mike,

Thanks for the help. It worked. I have another question but I will send it as a new thread.

Nihat

···

On Mon, Jun 30, 2008 at 12:02 PM, Michael Droettboom <mdroe@…86…> wrote:

Tony S Yu wrote:

On Jun 30, 2008, at 11:13 AM, Michael Droettboom wrote:

transScale is where all of the (optionally) logarithmic transformation takes place. I’m surprised

transDesired = self.transScale + self.transLimits

didn’t work for going from data to a (0, 0) - (1, 1) bounding box. Can you provide a small, yet complete, example that illustrates the bug so I can look at it further?

I tried to put together a simple example showing my problem, but the example worked properly! Doh!

It turns out that my problem was specific to using a bounding box as an input to transform:

=========

from numpy.random import rand

import matplotlib.pyplot as plt

ax = plt.subplot(111)

xy = rand(5,2)

ax.loglog(xy[:, 0], xy[:, 1], ‘ro’)

trans = ax.transScale + ax.transLimits

result = trans.transform(ax.dataLim) =========

The above command gives me:

  • TypeError:* ‘Bbox’ object is unsubscriptable

(Note, if I call plot instead of loglog I don’t have problems). The quick solution is to replace the last line with

result = trans.transform(ax.dataLim._points)

I guess I was confused because the transform worked fine with plot. Is the TypeError above expected behavior?

Yes. The “transform” method is meant to take an Nx2 array, it doesn’t take a bounding box. I think it probably works with non-log plots only by accident because bounding boxes can cast to arrays in some cases. It may be worth taking that out to avoid confusion, but I’ll have to think on it some.

Thanks for looking into this!

Mike

Michael Droettboom

Science Software Branch

Operations and Engineering Division

Space Telescope Science Institute

Operated by AURA for NASA