canvas.print_figure printing a variable amount of my figure

I feel like I must be missing something: below is some "minimal sample" code which reproduces a "problem" I'm seeing in a more complicated situation:

import matplotlib as MPL
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure

for DPI in range(100,201,25):
    fig = Figure(figsize=(12,9),
                 dpi=DPI,
                 frameon=False)
    canvas = FigureCanvas(fig)

    nx, ny = (N.uint16(12*DPI), N.uint16(9*DPI))
    temp = N.indices((ny, nx), N.uint8)
    result = N.zeros_like(temp[0])
    result[:ny/2,:] = temp[0,:ny/2,:] + temp[1,:ny/2,:]
    result[ny/2:,:] = temp[0,ny/2:,:] - temp[1,ny/2:,:]
    fig.figimage(result/N.float(N.max(result)))
    canvas.print_figure("test"+str(DPI)+"dpi.png")

Attached are the results on my computer (see usage details below). Granted, I'm increasing the resolution each iteration, but I'm always placing the "cut" in the figure half way through - why does the cut keep creeping up 'til it disappears?

Usage details: matplotlib version=? (I forget how to get that), numpy version = 1.0.4, Python version = 2.5.2, OS = Windows XPProSP3, 504 MB RAM w/ "Physical Address Extension" (whatever that means).

DG

PS: If the figures don't come through and for some reason my code doesn't work on your platform or doesn't reproduce the problem, email me and I'll email you the figures directly.

test100dpi.png

test125dpi.png

test150dpi.png

test175dpi.png

test200dpi.png

David Goldsmith wrote:

I feel like I must be missing something

yup -- though it's an understandable miss...

Attached are the results on my computer (see usage details below).
Granted, I'm increasing the resolution each iteration,

you are increasing the resolution of the figure, and of your calculations, but NOT of the output image. The hint was that every image was the same size: 1200X900 , which is 12"x9" at 100 dpi.

It turns out that print_figure() doesn't respect the figures (native DPI), it defaults to 100 dpi, but you can override it:

> canvas.print_figure("test"+str(DPI)+"dpi.png", dpi=DPI)

Then you'll get what I think you want.

Maybe this will help:

http://www.scipy.org/Cookbook/Matplotlib/AdjustingImageSize

though it there, I talked about Figure.savefig(). I don't know if there is a difference between that and Figure.print_figure()

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@...259...

Christopher Barker wrote:

David Goldsmith wrote:

I feel like I must be missing something

yup -- though it's an understandable miss...

I think the longstanding separation between the figure.dpi and the savefig.dpi is a continual gotcha that we can and should eliminate. Savefig should use the figure dpi, so that what is saved corresponds to what is on the screen, unless explicitly overridden. One way to reduce the problem, with what I hope is an adequate level of backwards compatibility, would be to have the savefig.dpi default to a special flag setting that means "track the figure.dpi". For example, savefig.dpi could be the string, 'screen', by default. This could still be overridden by a numerical rcParams setting, or by the explicit dpi kwarg setting in savefig() or print_figure().

There are still other highly confusing dpi things internally--such as a renderer.dpi setting that is ignored during rendering.

Comments?

Eric

···

Attached are the results on my computer (see usage details below).
Granted, I'm increasing the resolution each iteration,

you are increasing the resolution of the figure, and of your calculations, but NOT of the output image. The hint was that every image was the same size: 1200X900 , which is 12"x9" at 100 dpi.

It turns out that print_figure() doesn't respect the figures (native DPI), it defaults to 100 dpi, but you can override it:

> canvas.print_figure("test"+str(DPI)+"dpi.png", dpi=DPI)

Then you'll get what I think you want.

Maybe this will help:

http://www.scipy.org/Cookbook/Matplotlib/AdjustingImageSize

though it there, I talked about Figure.savefig(). I don't know if there is a difference between that and Figure.print_figure()

-Chris

Eric Firing wrote:

Christopher Barker wrote:

David Goldsmith wrote:

I feel like I must be missing something

yup -- though it's an understandable miss...

I think the longstanding separation between the figure.dpi and the
savefig.dpi is a continual gotcha that we can and should eliminate.
Savefig should use the figure dpi, so that what is saved corresponds to
what is on the screen, unless explicitly overridden. One way to reduce
the problem, with what I hope is an adequate level of backwards
compatibility, would be to have the savefig.dpi default to a special
flag setting that means "track the figure.dpi". For example,
savefig.dpi could be the string, 'screen', by default. This could still
be overridden by a numerical rcParams setting, or by the explicit dpi
kwarg setting in savefig() or print_figure().

There are still other highly confusing dpi things internally--such as a
renderer.dpi setting that is ignored during rendering.

Comments?

+1 On your suggestion. I agree this is confusing at times.
Unfortunately, I don't have any time to offer for code at this time.
(Hopefully more time for MPL soon!)

Ryan

···

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Eric Firing wrote:

I think the longstanding separation between the figure.dpi and the savefig.dpi is a continual gotcha that we can and should eliminate.

+1

I've never understood the separation -- why wouldn't it default to the figure.dpi -- it could always be overridden by the keyword arg anyway.

One way to reduce the problem, with what I hope is an adequate level of backwards compatibility, would be to have the savefig.dpi default to a special flag setting that means "track the figure.dpi". For example, savefig.dpi could be the string, 'screen', by default.

the thing is, this problem occurs even if there is no screen -- i.e. with just the Agg back-en, maybe "figure" or "preserve" or something?

> This could still

be overridden by a numerical rcParams setting, or by the explicit dpi kwarg setting in savefig() or print_figure().

well, either the default behavior is changed, or it's not. Are you proposing that the default rcParams setting be "screen" (or whatever), in which case it could be returned to the old behavior (set to 100?) with a change, if the user so chooses?

If so, I think I'd not bother. if the default change,s let folks learn to add a dpi keyword arg in their code.

If you were thinking that the default rcParam would be the current behavior, then I'm not sure we're removing the "gotcha".

I suppose another option would be to make the dpi argument non-optional -- then everyone would KNOW that needed to specify the dpi. Ugly, but no ones code would break without them knowing it broke.

Does MPL have a deprecation warning policy?

There are still other highly confusing dpi things internally--such as a renderer.dpi setting that is ignored during rendering.

I'm not familiar with this one, but I think it does make sense to address these all at once.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@...259...

The "solution" which worked well for me was to bite the bullet and switch to PIL for my image generating/processing needs. FWIW,

DG

···

--- On Mon, 10/6/08, Eric Firing <efiring@...202...> wrote:

From: Eric Firing <efiring@...202...>
Subject: Re: [Matplotlib-users] canvas.print_figure printing a variable amount of my figure
To: "Christopher Barker" <Chris.Barker@...259...>
Cc: "David Goldsmith" <d_l_goldsmith@...9...>, matplotlib-users@lists.sourceforge.net
Date: Monday, October 6, 2008, 11:56 AM
Christopher Barker wrote:
> David Goldsmith wrote:
>> I feel like I must be missing something
>
> yup -- though it's an understandable miss...

I think the longstanding separation between the figure.dpi
and the
savefig.dpi is a continual gotcha that we can and should
eliminate.
Savefig should use the figure dpi, so that what is saved
corresponds to
what is on the screen, unless explicitly overridden. One
way to reduce
the problem, with what I hope is an adequate level of
backwards
compatibility, would be to have the savefig.dpi default to
a special
flag setting that means "track the figure.dpi".
For example,
savefig.dpi could be the string, 'screen', by
default. This could still
be overridden by a numerical rcParams setting, or by the
explicit dpi
kwarg setting in savefig() or print_figure().

There are still other highly confusing dpi things
internally--such as a
renderer.dpi setting that is ignored during rendering.

Comments?

Eric

>
>
>> Attached are the results on my computer (see usage
details below).
>> Granted, I'm increasing the resolution each
iteration,
>
> you are increasing the resolution of the figure, and
of your
> calculations, but NOT of the output image. The hint
was that every image
> was the same size: 1200X900 , which is
12"x9" at 100 dpi.
>
> It turns out that print_figure() doesn't respect
the figures (native
> DPI), it defaults to 100 dpi, but you can override it:
>
> >
canvas.print_figure("test"+str(DPI)+"dpi.png",
dpi=DPI)
>
> Then you'll get what I think you want.
>
> Maybe this will help:
>
>
http://www.scipy.org/Cookbook/Matplotlib/AdjustingImageSize
>
> though it there, I talked about Figure.savefig(). I
don't know if there
> is a difference between that and Figure.print_figure()
>
> -Chris
>
>