Rotating in imshow

Hello,

I was wondering whether there is a way to rotate a grayscale/colorscale when using imshow.

I have been using PGPLOT (a fortran/c plotting library) for many years now, and the equivalent to imshow is called PGGRAY (or PGIMAG). One of the arguments this function takes is a 6-element array TR which is a transformation matrix. From the PGPLOT documentation:

"The transformation matrix TR is used to calculate the world coordinates of the center of the "cell" that represents each array element. The world coordinates of the center of the cell corresponding to array element A(I,J) are given by:
X = TR(1) + TR(2)*I + TR(3)*J
Y = TR(4) + TR(5)*I + TR(6)*J"

This is actually the same as the ImageMatrix element in the Postscript language:

"ImageMatrix array (Required) An array of six numbers defining a transformation from user
space to image space." (http://www.adobe.com/devnet/postscript/pdfs/PLRM.pdf, page 298)

This allows arbitrary rotation/translation of the image to plotting without any loss in quality for vector graphics formats (EPS, PDF, SVG).

So far, I have found that imshow has an 'extend' keyword, which is the equivalent of four of the matrix elements, but there is no way to specify the rotation. Is there such a feature in matplotlib already? If not, would it be possible to implement it?

Just to be clear, I am not talking about rotating with some kind of interpolation, which would degrade the image (this can be done with PIL). What I want is to be able to specify a transformation matrix which includes rotation, which means that there is no resampling done if I save my plot in a vector graphics format.

Thanks in advance for any help!

Thomas

Thomas Robitaille wrote:

Hello,

I was wondering whether there is a way to rotate a grayscale/ colorscale when using imshow.

I have been using PGPLOT (a fortran/c plotting library) for many years now, and the equivalent to imshow is called PGGRAY (or PGIMAG). One of the arguments this function takes is a 6-element array TR which is a transformation matrix. From the PGPLOT documentation:

"The transformation matrix TR is used to calculate the world coordinates of the center of the "cell" that represents each array element. The world coordinates of the center of the cell corresponding to array element A(I,J) are given by:
X = TR(1) + TR(2)*I + TR(3)*J
Y = TR(4) + TR(5)*I + TR(6)*J"

You could do this with the Axes.pcolormesh method. You could start with an unrotated grid (generated by meshgrid, for example), apply your rotation, and use that transformed grid in pcolormesh. Note that pcolormesh requires the grid for the cell boundaries, not centers.

Eric

···

This is actually the same as the ImageMatrix element in the Postscript language:

"ImageMatrix array (Required) An array of six numbers defining a transformation from user
space to image space." (http://www.adobe.com/devnet/postscript/pdfs/PLRM.pdf , page 298)

This allows arbitrary rotation/translation of the image to plotting without any loss in quality for vector graphics formats (EPS, PDF, SVG).

So far, I have found that imshow has an 'extend' keyword, which is the equivalent of four of the matrix elements, but there is no way to specify the rotation. Is there such a feature in matplotlib already? If not, would it be possible to implement it?

Just to be clear, I am not talking about rotating with some kind of interpolation, which would degrade the image (this can be done with PIL). What I want is to be able to specify a transformation matrix which includes rotation, which means that there is no resampling done if I save my plot in a vector graphics format.

Thanks in advance for any help!

Thomas

------------------------------------------------------------------------------
Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are
powering Web 2.0 with engaging, cross-platform capabilities. Quickly and
easily build your RIAs with Flex Builder, the Eclipse(TM)based development
software that enables intelligent coding and step-through debugging.
Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Eric Firing wrote:

Thomas Robitaille wrote:

Hello,

I was wondering whether there is a way to rotate a grayscale/
colorscale when using imshow.

I have been using PGPLOT (a fortran/c plotting library) for many years
now, and the equivalent to imshow is called PGGRAY (or PGIMAG). One of
the arguments this function takes is a 6-element array TR which is a
transformation matrix. From the PGPLOT documentation:

"The transformation matrix TR is used to calculate the world
coordinates of the center of the "cell" that represents each array
element. The world coordinates of the center of the cell corresponding
to array element A(I,J) are given by:
X = TR(1) + TR(2)*I + TR(3)*J
Y = TR(4) + TR(5)*I + TR(6)*J"

You could do this with the Axes.pcolormesh method. You could start with
an unrotated grid (generated by meshgrid, for example), apply your
rotation, and use that transformed grid in pcolormesh. Note that
pcolormesh requires the grid for the cell boundaries, not centers.

It should work with imshow() as well if you can set the affine component
of the transform to the desired values. Which it looks like you can in
Affine2D(). (The affine matrix is the elements of TR listed above, it
appears.)

I have not tried to do this, however -- just saying that I think it's
possible.

-Andrew

Thanks to both of you for your help! I had spotted the transform argument in imshow, but didn't manage to find any information about how to use it. The Affine2D method looks like it will help, so I should be all set now.

Thanks!

Thomas

···

On Mar 13, 2009, at 5:20 PM, Andrew Straw wrote:

Eric Firing wrote:

Thomas Robitaille wrote:

Hello,

I was wondering whether there is a way to rotate a grayscale/
colorscale when using imshow.

I have been using PGPLOT (a fortran/c plotting library) for many years
now, and the equivalent to imshow is called PGGRAY (or PGIMAG). One of
the arguments this function takes is a 6-element array TR which is a
transformation matrix. From the PGPLOT documentation:

"The transformation matrix TR is used to calculate the world
coordinates of the center of the "cell" that represents each array
element. The world coordinates of the center of the cell corresponding
to array element A(I,J) are given by:
X = TR(1) + TR(2)*I + TR(3)*J
Y = TR(4) + TR(5)*I + TR(6)*J"

You could do this with the Axes.pcolormesh method. You could start with
an unrotated grid (generated by meshgrid, for example), apply your
rotation, and use that transformed grid in pcolormesh. Note that
pcolormesh requires the grid for the cell boundaries, not centers.

It should work with imshow() as well if you can set the affine component
of the transform to the desired values. Which it looks like you can in
Affine2D(). (The affine matrix is the elements of TR listed above, it
appears.)

I have not tried to do this, however -- just saying that I think it's
possible.

-Andrew

It looks like rotation/translation should be easy to do with Affine2D, so I tried using it, but I can't seem to get it to work as expected - here is an example of how I am using it:

import numpy as np
from matplotlib.pyplot import *
from matplotlib.transforms import Affine2D

im = np.random.random((10,10))
tr = Affine2D().rotate_deg(45.)

fig = figure()
ax = fig.add_subplot(111)
ax.imshow(im,transform=tr)
fig.canvas.draw()

Am I doing something wrong?

Thanks!

Thomas

···

On Mar 13, 2009, at 5:20 PM, Andrew Straw wrote:

Eric Firing wrote:

Thomas Robitaille wrote:

Hello,

I was wondering whether there is a way to rotate a grayscale/
colorscale when using imshow.

I have been using PGPLOT (a fortran/c plotting library) for many years
now, and the equivalent to imshow is called PGGRAY (or PGIMAG). One of
the arguments this function takes is a 6-element array TR which is a
transformation matrix. From the PGPLOT documentation:

"The transformation matrix TR is used to calculate the world
coordinates of the center of the "cell" that represents each array
element. The world coordinates of the center of the cell corresponding
to array element A(I,J) are given by:
X = TR(1) + TR(2)*I + TR(3)*J
Y = TR(4) + TR(5)*I + TR(6)*J"

You could do this with the Axes.pcolormesh method. You could start with
an unrotated grid (generated by meshgrid, for example), apply your
rotation, and use that transformed grid in pcolormesh. Note that
pcolormesh requires the grid for the cell boundaries, not centers.

It should work with imshow() as well if you can set the affine component
of the transform to the desired values. Which it looks like you can in
Affine2D(). (The affine matrix is the elements of TR listed above, it
appears.)

I have not tried to do this, however -- just saying that I think it's
possible.

-Andrew

Thomas Robitaille wrote:

It looks like rotation/translation should be easy to do with Affine2D, so I tried using it, but I can't seem to get it to work as expected - here is an example of how I am using it:

Based on a quick look at image.py and _image.cpp, it appears that there is a low-level capability to rotate an image in the latter, but no support at higher levels. It also looks to me like adding that support would not be trivial--doing it right would take more than just calling the low-level apply_rotation method. Mike D. would be the expert on this, though.

Eric

···

import numpy as np
from matplotlib.pyplot import *
from matplotlib.transforms import Affine2D

im = np.random.random((10,10))
tr = Affine2D().rotate_deg(45.)

fig = figure()
ax = fig.add_subplot(111)
ax.imshow(im,transform=tr)
fig.canvas.draw()

Am I doing something wrong?

Thanks!

Thomas

On Mar 13, 2009, at 5:20 PM, Andrew Straw wrote:

Eric Firing wrote:

Thomas Robitaille wrote:

Hello,

I was wondering whether there is a way to rotate a grayscale/
colorscale when using imshow.

I have been using PGPLOT (a fortran/c plotting library) for many years
now, and the equivalent to imshow is called PGGRAY (or PGIMAG). One of
the arguments this function takes is a 6-element array TR which is a
transformation matrix. From the PGPLOT documentation:

"The transformation matrix TR is used to calculate the world
coordinates of the center of the "cell" that represents each array
element. The world coordinates of the center of the cell corresponding
to array element A(I,J) are given by:
X = TR(1) + TR(2)*I + TR(3)*J
Y = TR(4) + TR(5)*I + TR(6)*J"

You could do this with the Axes.pcolormesh method. You could start with
an unrotated grid (generated by meshgrid, for example), apply your
rotation, and use that transformed grid in pcolormesh. Note that
pcolormesh requires the grid for the cell boundaries, not centers.

It should work with imshow() as well if you can set the affine component
of the transform to the desired values. Which it looks like you can in
Affine2D(). (The affine matrix is the elements of TR listed above, it
appears.)

I have not tried to do this, however -- just saying that I think it's
possible.

-Andrew

It looks like rotation/translation should be easy to do with Affine2D, so I tried using it, but I can't seem to get it to work as expected - here is an example of how I am using it:

Based on a quick look at image.py and _image.cpp, it appears that there is a low-level capability to rotate an image in the latter, but no support at higher levels. It also looks to me like adding that support would not be trivial--doing it right would take more than just calling the low-level apply_rotation method. Mike D. would be the expert on this, though.

Does this mean that the transform= keyword has no effect on imshow in general?

I tried doing a simple image translation, and this didn't work either:

import numpy as np
from matplotlib.pyplot import *
from matplotlib.transforms import Affine2D
im = np.random.random((10,10))
tr = Affine2D().translate(10.,10.)
fig = figure()
ax = fig.add_subplot(111)
ax.imshow(im,transform=tr)
fig.canvas.draw()

I attempted to use the pcolormesh() method, which worked, but is impractical, as a 1000x1000 image produces a 300Mb EPS file when plotted in this way.

Thanks,

Thomas

···

Eric

import numpy as np
from matplotlib.pyplot import *
from matplotlib.transforms import Affine2D
im = np.random.random((10,10))
tr = Affine2D().rotate_deg(45.)
fig = figure()
ax = fig.add_subplot(111)
ax.imshow(im,transform=tr)
fig.canvas.draw()
Am I doing something wrong?
Thanks!
Thomas
On Mar 13, 2009, at 5:20 PM, Andrew Straw wrote:

Eric Firing wrote:

Thomas Robitaille wrote:

Hello,

I was wondering whether there is a way to rotate a grayscale/
colorscale when using imshow.

I have been using PGPLOT (a fortran/c plotting library) for many years
now, and the equivalent to imshow is called PGGRAY (or PGIMAG). One of
the arguments this function takes is a 6-element array TR which is a
transformation matrix. From the PGPLOT documentation:

"The transformation matrix TR is used to calculate the world
coordinates of the center of the "cell" that represents each array
element. The world coordinates of the center of the cell corresponding
to array element A(I,J) are given by:
X = TR(1) + TR(2)*I + TR(3)*J
Y = TR(4) + TR(5)*I + TR(6)*J"

You could do this with the Axes.pcolormesh method. You could start with
an unrotated grid (generated by meshgrid, for example), apply your
rotation, and use that transformed grid in pcolormesh. Note that
pcolormesh requires the grid for the cell boundaries, not centers.

It should work with imshow() as well if you can set the affine component
of the transform to the desired values. Which it looks like you can in
Affine2D(). (The affine matrix is the elements of TR listed above, it
appears.)

I have not tried to do this, however -- just saying that I think it's
possible.

-Andrew

Thomas Robitaille wrote:

It looks like rotation/translation should be easy to do with Affine2D, so I tried using it, but I can't seem to get it to work as expected - here is an example of how I am using it:

Based on a quick look at image.py and _image.cpp, it appears that there is a low-level capability to rotate an image in the latter, but no support at higher levels. It also looks to me like adding that support would not be trivial--doing it right would take more than just calling the low-level apply_rotation method. Mike D. would be the expert on this, though.

Does this mean that the transform= keyword has no effect on imshow in general?

It does look like it is ignored. It is a kwarg for Artists that is not supported by all. The fact that one can specify it and get no feedback is a bug.

I attempted to use the pcolormesh() method, which worked, but is impractical, as a 1000x1000 image produces a 300Mb EPS file when plotted in this way.

There is some infrastructure for handling this via selective rasterization of artists, but I can never remember exactly what its status is; I don't see anything in the examples. The topic comes up on the list at perhaps 6-month intervals. Personally, I would very much like to see the selective rasterization capability fully developed and exposed, complete with documentation and examples; it is important for exactly the reason you note above. It is not something I will be able to work on myself, unfortunately.

Eric

Just getting back to work after an illness...

Eric's assessment is 100% correct: the transform kwarg is ignored by images. It probably could be, but it would not be trivial, particularly in the way the Agg backend is currently architected. This should probably be added as a feature request to the tracker, so we don't forget about it.

As for selective rasterization, IIRC we never really got past the API discussion. That's all that really needs to be done -- have a consistent sensical API for it -- other than that, I believe it works in PDF, PS and SVG backends already (probably not Cairo ATM, though).

Mike

Eric Firing wrote:

···

Thomas Robitaille wrote:
  

It looks like rotation/translation should be easy to do with Affine2D, so I tried using it, but I can't seem to get it to work as expected - here is an example of how I am using it:
        

Based on a quick look at image.py and _image.cpp, it appears that there is a low-level capability to rotate an image in the latter, but no support at higher levels. It also looks to me like adding that support would not be trivial--doing it right would take more than just calling the low-level apply_rotation method. Mike D. would be the expert on this, though.
      

Does this mean that the transform= keyword has no effect on imshow in general?
    
It does look like it is ignored. It is a kwarg for Artists that is not supported by all. The fact that one can specify it and get no feedback is a bug.

I attempted to use the pcolormesh() method, which worked, but is impractical, as a 1000x1000 image produces a 300Mb EPS file when plotted in this way.
    
There is some infrastructure for handling this via selective rasterization of artists, but I can never remember exactly what its status is; I don't see anything in the examples. The topic comes up on the list at perhaps 6-month intervals. Personally, I would very much like to see the selective rasterization capability fully developed and exposed, complete with documentation and examples; it is important for exactly the reason you note above. It is not something I will be able to work on myself, unfortunately.
  
--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA