Exporting plot with given scale and DPI

Hi all.

I use matplotlib inside PyQt app and want to export plot into PNG image with
some user-defined scale and DPI. So after printing that image I should be able
to measure on the paper according to the scale.

For example, length of the profile line is 500m (this is my x-axis),
scale set to 1:10000 and DPI is 150. 500m at 1:10000 should result in
a 5cm print out. Taking 150 DPI into account resulting bitmap should
be 295 pixels wide:

1cm is 0.393701 inches
5cm is 1.968505 inches
1.968505inches * 150DPI = 295.27575 px

Also it is necessary to take into account that resulting image may be
really big, for
example if profile line length is several kilometers and DPI is 600.

As I can see there is a 'dpi' parameter in the savefig() call, but I
can't figure out how
to adjust size of the existing figure when exporting. Can you help me?

Thanks

···

--
Alexander Bruy

Does `fig.set_size_inches()` do what you want?

Cheers, Jody

···

On 8 Jan 2018, at 08:44, Alexander Bruy <alexander.bruy at gmail.com> wrote:

Hi all.

I use matplotlib inside PyQt app and want to export plot into PNG image with
some user-defined scale and DPI. So after printing that image I should be able
to measure on the paper according to the scale.

For example, length of the profile line is 500m (this is my x-axis),
scale set to 1:10000 and DPI is 150. 500m at 1:10000 should result in
a 5cm print out. Taking 150 DPI into account resulting bitmap should
be 295 pixels wide:

1cm is 0.393701 inches
5cm is 1.968505 inches
1.968505inches * 150DPI = 295.27575 px

Also it is necessary to take into account that resulting image may be
really big, for
example if profile line length is several kilometers and DPI is 600.

As I can see there is a 'dpi' parameter in the savefig() call, but I
can't figure out how
to adjust size of the existing figure when exporting. Can you help me?

Thanks
--
Alexander Bruy
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
https://mail.python.org/mailman/listinfo/matplotlib-users

--
Jody Klymak
http://web.uvic.ca/~jklymak/

It is not clear from the docs if this function preserves dimensions and DPI
when exporting plot into PNG.

Also as I understand it resizes plot on screen and does not play well with
large sizes.

2018-01-08 19:20 GMT+02:00 Jody Klymak <jklymak at uvic.ca>:

···

Does `fig.set_size_inches()` do what you want?

Cheers, Jody

On 8 Jan 2018, at 08:44, Alexander Bruy <alexander.bruy at gmail.com> wrote:

Hi all.

I use matplotlib inside PyQt app and want to export plot into PNG image with
some user-defined scale and DPI. So after printing that image I should be able
to measure on the paper according to the scale.

For example, length of the profile line is 500m (this is my x-axis),
scale set to 1:10000 and DPI is 150. 500m at 1:10000 should result in
a 5cm print out. Taking 150 DPI into account resulting bitmap should
be 295 pixels wide:

1cm is 0.393701 inches
5cm is 1.968505 inches
1.968505inches * 150DPI = 295.27575 px

Also it is necessary to take into account that resulting image may be
really big, for
example if profile line length is several kilometers and DPI is 600.

As I can see there is a 'dpi' parameter in the savefig() call, but I
can't figure out how
to adjust size of the existing figure when exporting. Can you help me?

Thanks
--
Alexander Bruy
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
https://mail.python.org/mailman/listinfo/matplotlib-users

--
Jody Klymak
http://web.uvic.ca/~jklymak/

--
Alexander Bruy

You are correct that if you are displaying a plot on the screen, the
figure size will be changed to fit. This is a shortcoming of all the
mpl backends; the plot windows should have automatic scrollbars instead.
The workaround is simple, though: When you make the figure, use a small
enough dpi so that the window will fit on the screen. Then use your
desired dpi when you save:

fig, ax = plt.subplots(figsize=(20,30), dpi=20)
# ... plot something...
fig.savefig('bigplot.png', dpi=150)

Assuming you have a typical screen size, the above will result in the
following output from the "file" command (in Linux or OSX):

bigplot.png: PNG image data, 3000 x 4500, 8-bit/color RGBA, non-interlaced

As you see, it is consistent with the requested figsize and file dpi.

Eric

···

On 2018/01/08 7:45 AM, Alexander Bruy wrote:

It is not clear from the docs if this function preserves dimensions and DPI
when exporting plot into PNG.

Also as I understand it resizes plot on screen and does not play well with
large sizes.

2018-01-08 19:20 GMT+02:00 Jody Klymak <jklymak at uvic.ca>:

Does `fig.set_size_inches()` do what you want?

Cheers, Jody

On 8 Jan 2018, at 08:44, Alexander Bruy <alexander.bruy at gmail.com> wrote:

Hi all.

I use matplotlib inside PyQt app and want to export plot into PNG image with
some user-defined scale and DPI. So after printing that image I should be able
to measure on the paper according to the scale.

For example, length of the profile line is 500m (this is my x-axis),
scale set to 1:10000 and DPI is 150. 500m at 1:10000 should result in
a 5cm print out. Taking 150 DPI into account resulting bitmap should
be 295 pixels wide:

1cm is 0.393701 inches
5cm is 1.968505 inches
1.968505inches * 150DPI = 295.27575 px

Also it is necessary to take into account that resulting image may be
really big, for
example if profile line length is several kilometers and DPI is 600.

As I can see there is a 'dpi' parameter in the savefig() call, but I
can't figure out how
to adjust size of the existing figure when exporting. Can you help me?

Thanks
--
Alexander Bruy
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
https://mail.python.org/mailman/listinfo/matplotlib-users

--
Jody Klymak
http://web.uvic.ca/~jklymak/

Hi,

thanks for the hints, I have adopted your suggestions but still have
some issues.
Now my workflow looks like this:
1. get scale and DPI from user
2. calculate figure width and height in inches based on scale and DPI
3. make a figure with calculated width and height and small DPI value
    fig = plt.figure(figsize=(imgWidth, imgWidth), dpi=10)
4. plot profile line
5. export figure with correct DPI
    fig.savefig(fileName, dpi=int(userDPI), format="png", bbox_inches="tight")

Unfortunately, when I export figure with correct DPI I get incorrect image
dimensions. After some experiments, I have found that adding fig.show()
*before* the savefig() call fixes things and resulting image is correct.

Here is the image obtained without fig.show()
for example https://ibb.co/dx03E6

And here is correct result I get with fig.show() added before savefig()
https://ibb.co/gZ0ygm

Any ideas what can be wrong? I tried to remove bbox_inches="tight" but
still no luck, output is not correct anyway. Using mpl.use('Agg') or similar
things is not possible as matplotlib embeeded into Qt application.

I can live with fig.show() workaround, but need a way to close plot window
programmaticaly after saving the figure.

2018-01-08 21:29 GMT+02:00 Eric Firing <efiring at hawaii.edu>:

···

You are correct that if you are displaying a plot on the screen, the figure
size will be changed to fit. This is a shortcoming of all the mpl backends;
the plot windows should have automatic scrollbars instead. The workaround is
simple, though: When you make the figure, use a small enough dpi so that the
window will fit on the screen. Then use your desired dpi when you save:

fig, ax = plt.subplots(figsize=(20,30), dpi=20)
# ... plot something...
fig.savefig('bigplot.png', dpi=150)

Assuming you have a typical screen size, the above will result in the
following output from the "file" command (in Linux or OSX):

bigplot.png: PNG image data, 3000 x 4500, 8-bit/color RGBA, non-interlaced

As you see, it is consistent with the requested figsize and file dpi.

Eric

On 2018/01/08 7:45 AM, Alexander Bruy wrote:

It is not clear from the docs if this function preserves dimensions and
DPI
when exporting plot into PNG.

Also as I understand it resizes plot on screen and does not play well with
large sizes.

2018-01-08 19:20 GMT+02:00 Jody Klymak <jklymak at uvic.ca>:

Does `fig.set_size_inches()` do what you want?

Cheers, Jody

On 8 Jan 2018, at 08:44, Alexander Bruy <alexander.bruy at gmail.com> >>>> wrote:

Hi all.

I use matplotlib inside PyQt app and want to export plot into PNG image
with
some user-defined scale and DPI. So after printing that image I should
be able
to measure on the paper according to the scale.

For example, length of the profile line is 500m (this is my x-axis),
scale set to 1:10000 and DPI is 150. 500m at 1:10000 should result in
a 5cm print out. Taking 150 DPI into account resulting bitmap should
be 295 pixels wide:

1cm is 0.393701 inches
5cm is 1.968505 inches
1.968505inches * 150DPI = 295.27575 px

Also it is necessary to take into account that resulting image may be
really big, for
example if profile line length is several kilometers and DPI is 600.

As I can see there is a 'dpi' parameter in the savefig() call, but I
can't figure out how
to adjust size of the existing figure when exporting. Can you help me?

Thanks
--
Alexander Bruy
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
https://mail.python.org/mailman/listinfo/matplotlib-users

--
Jody Klymak
http://web.uvic.ca/~jklymak/

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
https://mail.python.org/mailman/listinfo/matplotlib-users

--
Alexander Bruy

It looks like somewhere you are setting an aspect ratio of 1 (or
'equal') and the difference between the examples is that the first is
with adjustable 'box' and the second is with adjustable 'datalim'.

Are you doing any sharing or twinning of axes?

In place of the call to show, try putting in

ax.set_aspect('datalim')
ax.apply_aspect()

Eric

···

On 2018/01/09 6:58 AM, Alexander Bruy wrote:

Hi,

thanks for the hints, I have adopted your suggestions but still have
some issues.
Now my workflow looks like this:
1. get scale and DPI from user
2. calculate figure width and height in inches based on scale and DPI
3. make a figure with calculated width and height and small DPI value
     fig = plt.figure(figsize=(imgWidth, imgWidth), dpi=10)
4. plot profile line
5. export figure with correct DPI
     fig.savefig(fileName, dpi=int(userDPI), format="png", bbox_inches="tight")

Unfortunately, when I export figure with correct DPI I get incorrect image
dimensions. After some experiments, I have found that adding fig.show()
*before* the savefig() call fixes things and resulting image is correct.

Here is the image obtained without fig.show()
for example https://ibb.co/dx03E6

And here is correct result I get with fig.show() added before savefig()
https://ibb.co/gZ0ygm

Any ideas what can be wrong? I tried to remove bbox_inches="tight" but
still no luck, output is not correct anyway. Using mpl.use('Agg') or similar
things is not possible as matplotlib embeeded into Qt application.

I can live with fig.show() workaround, but need a way to close plot window
programmaticaly after saving the figure.

2018-01-08 21:29 GMT+02:00 Eric Firing <efiring at hawaii.edu>:

You are correct that if you are displaying a plot on the screen, the figure
size will be changed to fit. This is a shortcoming of all the mpl backends;
the plot windows should have automatic scrollbars instead. The workaround is
simple, though: When you make the figure, use a small enough dpi so that the
window will fit on the screen. Then use your desired dpi when you save:

fig, ax = plt.subplots(figsize=(20,30), dpi=20)
# ... plot something...
fig.savefig('bigplot.png', dpi=150)

Assuming you have a typical screen size, the above will result in the
following output from the "file" command (in Linux or OSX):

bigplot.png: PNG image data, 3000 x 4500, 8-bit/color RGBA, non-interlaced

As you see, it is consistent with the requested figsize and file dpi.

Eric

On 2018/01/08 7:45 AM, Alexander Bruy wrote:

It is not clear from the docs if this function preserves dimensions and
DPI
when exporting plot into PNG.

Also as I understand it resizes plot on screen and does not play well with
large sizes.

2018-01-08 19:20 GMT+02:00 Jody Klymak <jklymak at uvic.ca>:

Does `fig.set_size_inches()` do what you want?

Cheers, Jody

On 8 Jan 2018, at 08:44, Alexander Bruy <alexander.bruy at gmail.com> >>>>> wrote:

Hi all.

I use matplotlib inside PyQt app and want to export plot into PNG image
with
some user-defined scale and DPI. So after printing that image I should
be able
to measure on the paper according to the scale.

For example, length of the profile line is 500m (this is my x-axis),
scale set to 1:10000 and DPI is 150. 500m at 1:10000 should result in
a 5cm print out. Taking 150 DPI into account resulting bitmap should
be 295 pixels wide:

1cm is 0.393701 inches
5cm is 1.968505 inches
1.968505inches * 150DPI = 295.27575 px

Also it is necessary to take into account that resulting image may be
really big, for
example if profile line length is several kilometers and DPI is 600.

As I can see there is a 'dpi' parameter in the savefig() call, but I
can't figure out how
to adjust size of the existing figure when exporting. Can you help me?

Thanks
--
Alexander Bruy
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
https://mail.python.org/mailman/listinfo/matplotlib-users

--
Jody Klymak
http://web.uvic.ca/~jklymak/

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
https://mail.python.org/mailman/listinfo/matplotlib-users

Hi Eric,

2018-01-10 18:46 GMT+02:00 Eric Firing <efiring at hawaii.edu>:

It looks like somewhere you are setting an aspect ratio of 1 (or 'equal')
and the difference between the examples is that the first is with adjustable
'box' and the second is with adjustable 'datalim'.

Right, I create axes using following code:

axes = fig.add_axes((LEFT_MARGIN, BOTTOM_MARGIN, RIGHT_MARGIN, TOP_MARGIN),
                                  adjustable="datalim", aspect=1)

Are you doing any sharing or twinning of axes?

No sharing or twinning, just single line and one pair (X and Y) of axes.

···

--
Alexander Bruy

Can you give us a minimal self-contained working example of exactly what you are trying to do?

Cheers, Jody

···

On 10 Jan 2018, at 09:58, Alexander Bruy <alexander.bruy at gmail.com> wrote:

Hi Eric,

2018-01-10 18:46 GMT+02:00 Eric Firing <efiring at hawaii.edu>:

It looks like somewhere you are setting an aspect ratio of 1 (or 'equal')
and the difference between the examples is that the first is with adjustable
'box' and the second is with adjustable 'datalim'.

Right, I create axes using following code:

axes = fig.add_axes((LEFT_MARGIN, BOTTOM_MARGIN, RIGHT_MARGIN, TOP_MARGIN),
                                 adjustable="datalim", aspect=1)

Are you doing any sharing or twinning of axes?

No sharing or twinning, just single line and one pair (X and Y) of axes.

--
Alexander Bruy
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
https://mail.python.org/mailman/listinfo/matplotlib-users

--
Jody Klymak
http://web.uvic.ca/~jklymak/