Plotting a matrix in some region

Hi,

today I urgently needed to plot a matrix in a given
region of a plot. It seems that imshow does not
support this (at least I could not find how)
and I don't understand the internals well
enough to add such a feature.
As work-around I have set up the quick hack listed
at the end of this mail.
It is not really complicated, but
maybe it is useful to someone else.

Note, that there are a couple of problems:
- zooming does not work as expected
  (the displayed matrix stays fixed in absolute coords wrt to
   the current graph)
- drawing a line over the shown bitmap is not possible
- presumably more

Is there a way to this better with imshow?

Best,

Arnd

···

#########################
from pylab import *

def plot_mat(mat,extent=None):
    """ Plot a matrix (or whatever suits imshow) at
        the place defined by extent=[x0,x1,y0,y1].
        """
    g=gca()
    l,b,w,h=g.get_position()
    x0,x1=g.get_xlim()
    y0,y1=g.get_ylim()

    #print "Axes coords of curr axes:",l,b,w,h
    #print "Ranges:",x0,x1,y0,y1

    if extent!=None:
        inset_x0=extent[0]
        inset_x1=extent[1]
        inset_y0=extent[2]
        inset_y1=extent[3]
    else:
        inset_x0=x0
        inset_x1=x1
        inset_y0=y0
        inset_y1=y1

    #print "WANTED:",inset_x0,inset_x1,inset_y0,inset_y1

    inset_w=w*(inset_x1-inset_x0)/(x1-x0)
    inset_h=h*(inset_y1-inset_y0)/(y1-y0)
    inset_l=l+(inset_x0-x0)/(x1-x0)*w
    inset_b=b+(inset_y0-y0)/(y1-y0)*h

    #print "RESULT:",inset_l , inset_b , inset_w , inset_h

    ax=axes( [inset_l , inset_b , inset_w , inset_h],axisbg="y")
    setp(ax,xticks=[],yticks=[])
    imshow(arr,interpolation="nearest")

# 2D
arr=reshape(arange(25),(5,5))

# 1D plot
x=arange(2.0,10.0,0.1)
line1,=plot(x,x**2)
line2,=plot(x,x**2)

#draw()

plot_mat(arr,extent=[5.0,8.0,15.0,50.0])

# Problem: try to plot this over the other plot,
# does not work
setp(line2,data=(x,0.25*x**3),zorder=1000)

show()

today I urgently needed to plot a matrix in a given

  > region of a plot. It seems that imshow does not
  > support this (at least I could not find how)
  > and I don't understand the internals well
  > enough to add such a feature.
  > As work-around I have set up the quick hack listed
  > at the end of this mail.
  > It is not really complicated, but
  > maybe it is useful to someone else.

If I'm understanding you correctly, you want to set the "extent"
argument of imshow

from pylab import *
arr=reshape(arange(25),(5,5))

imshow(arr, extent=[5.0,8.0,15.0,50.0])
x=arange(2.0,10.0,0.1)
line1,=plot(x,x**2)
line2,=plot(x,x**2)
setp(line2,data=(x,0.25*x**3),zorder=1000)
show()

  > Note, that there are a couple of problems:
  > - zooming does not work as expected
  > (the displayed matrix stays fixed in absolute coords wrt to
  > the current graph)
  > - drawing a line over the shown bitmap is not possible
  > - presumably more

The approach above should fix these three problems.

JDH

···

On 9/1/05, Arnd Baecker <arnd.baecker@...273...> wrote:

Hi John,

thank you very much for your quick reply!
It seems things are slightly more complicated, though...

  > today I urgently needed to plot a matrix in a given
  > region of a plot. It seems that imshow does not
  > support this (at least I could not find how)
  > and I don't understand the internals well
  > enough to add such a feature.
  > As work-around I have set up the quick hack listed
  > at the end of this mail.
  > It is not really complicated, but
  > maybe it is useful to someone else.

If I'm understanding you correctly, you want to set the "extent"
argument of imshow

Well, I thought so too, but I also need `axis("equal")`
and depending on the order of setting the
axis intervals (`axis([-0.35,2.1,-0.2,1.25])`)
before or after this, one obtains completely different results.

Below is an example, where this is illustrated,
by changing the code at the places marked by ===>.

So the example I posted was stripped down too strongly
(and your solution does work for that case!).

Best,

Arnd

P.S.: I ran my test with yesterdays CVS.

···

On Thu, 1 Sep 2005, John Hunter wrote:

On 9/1/05, Arnd Baecker <arnd.baecker@...273...> wrote:

###################
from pylab import *

# ===> uncommenting this gives a different result:
#ax=subplot(111,autoscale_on=False)

# ===> changing the order of these two gives different results:
axis("equal")
axis([-0.35,2.1,-0.2,1.25])
    # (note that -0.2 and 1.25 are not respected)

arr=reshape(arange(25),(5,5))

# ===> commenting this one out, when autoscale_on=False
# gives the expected result
imshow(arr, extent=[0.5,1.0,0.2,0.8])

# plot a circle to see if the aspect ratio is correct:
phi=arange(0.0,2.0*pi,0.01)
x=0.5*cos(phi)+0.5
y=0.5*sin(phi)+0.5

plot(x,y,lw="8")

show()

Hi John,

I looked a little bit further into this,
and maybe there is a simple solution:

In imshow (axes.py): if I comment out the lines

        #corners = (xmin, ymin), (xmax, ymax)
        #self.update_datalim(corners)
        #self.set_xlim((xmin, xmax))
        #self.set_ylim((ymin, ymax))

it works fine for the example I sent yesterday.
(only the different behaviour when changing the order
of `axis("equal")` and `axis([-0.35,2.1,-0.2,1.25])`
persists.)

So maybe it is already enough to encapsulate the above
part by `if autoscale_on==True`?
I am sorry that I can't help more here, but I just don't understand
the internals of matplotlib well enough.

Best,

Arnd