Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using matplotlib, how can I print something "actual size"?

I have a number of plots where the x- and y-axes are in centimeter units, and I am already using axis('equal') to ensure proper aspect ratios. I would like to print out those plots so that when I measure distances within my axes, the distances correspond to real-world centimeters.

That is, a line that is 3 units (cm) long in the plot should print out to be 3 cm long. (A more complex example would be drawing a ruler in Matplotlib, and then printing it out for use /as/ a ruler.) I found solutions in matlab and mathematica, but not for Matplotlib. Is there a magic formula to achieve this? I believe it will require a special combination/ordering of: figure(figsize=??), axis('equal'), fig.canvas.draw(), fig.savefig('filename',format="??"), possibly some math with fig.bbox parameters, and perhaps one or more dpi-settings. I have tried many combinations but haven't hit on the right one. And maybe there is a way-easier approach ...

like image 971
GaryS Avatar asked Apr 01 '15 20:04

GaryS


People also ask

How do you calculate the size of a figure in Matplotlib?

First, we write a general function to get the size of a figure. We then calculate x to set = x set previously x target x actual for x being the width and height. The intuition behind this equation is that we figure out how off the actual image’s size is from our target, and use this to update what we tell matplotlib to do.

Why does Matplotlib repeat the image size equation?

The intuition behind this equation is that we figure out how off the actual image’s size is from our target, and use this to update what we tell matplotlib to do. However, this is an approximation, and we repeat it to get a better fit.

How to change the size of the plot in Python?

Inside the figure method, you have to pass the fig size as width and height as a tuple. For example, If I want to change the size of the plot to the width of 8 inches and a height of 3 inches, then I will execute the following lines of code. The other method to change the size of the plot is using the plt.rcParams [“figure.figsize”].

What is the intuition behind Matplotlib’s size equation?

The intuition behind this equation is that we figure out how off the actual image’s size is from our target, and use this to update what we tell matplotlib to do. However, this is an approximation, and we repeat it to get a better fit. The full code is below:


2 Answers

Consider this example. Where I specify exactly the dimension of my axes in cm. matplotlib works in inches, so I convert to inches. And then I also save it with a particular dpi (128) so that it matches the designed dimensions in my display. This of course varies for every display. I found that by trial and error, even though there might be other methods. Well here the code:

left_margin = 1.   # cm
right_margin = 1.  # cm
figure_width = 10. # cm
figure_height = 7. # cm
top_margin = 1.    # cm
bottom_margin = 1. # cm

box_width = left_margin + figure_width + right_margin   # cm
box_height = top_margin + figure_height + bottom_margin # cm

cm2inch = 1/2.54 # inch per cm

# specifying the width and the height of the box in inches
fig = figure(figsize=(box_width*cm2inch,box_height*cm2inch))
ax = fig.add_subplot(111)
ax.plot([1,2,3])

fig.subplots_adjust(left   = left_margin / box_width,
                    bottom = bottom_margin / box_height,
                    right  = 1. - right_margin / box_width,
                    top    = 1. - top_margin   / box_height,
                    )
fig.savefig('ten_x_seven_cm.png', dpi=128)
# dpi = 128 is what works in my display for matching the designed dimensions.
like image 136
Pablo Reyes Avatar answered Nov 03 '22 01:11

Pablo Reyes


Add this to @pablo reyes' answer, check that the printer is at 100%, and it's pretty close;

ax.set_ylim(0,7)
ax.set_xlim(0,10)

ax.plot([0.5, 1.5],[0.25, 0.25],label='One cm?')
ax.plot([6,6],[1,2], label='One cm?')
ax.legend()

we force the axis to be a size we know, we make its data-transform match the real world, and we can "print a ruler".

like image 28
cphlewis Avatar answered Nov 03 '22 01:11

cphlewis