Home > Back-end >  How to display python plots at real resolution on screen
How to display python plots at real resolution on screen

Time:02-08

I can control dpi, and the scaling of the axis just fine, I just need method for reliably displaying the plot pixel for pixel on whatever digital screen I am using.

Displaying them on a digital screen has proven tricky. I have taken into account the dpi of the screen and factoring that in generation of the plot. The most reliable way I have found to display the plots has been to save them as a .png file and open them up in MS paint. I initially had success with matplotlib's standard plot viewer, however, it has proven unreliable when using a 4k screen for some reason I cannot explain even after taking into account the dpi change. I'd really love use the standard viewer as it is simple and you can even probe the image if you'd like but the unreliable scaling kills this option for me. I did some research whether there were parameters that could lock the scaling functionality of the window and keep it at its native resolution but found none.

I have tried some other libraries such as PIL to display the image but that uses the OS image viewer which displays it at the most convenient size.

Some ideas floating in my head are:

  • pygame. I have tinkered with that library and it offers some good pixel control functionality.
  • Alternative display functions built into matplotlib that I am simply not aware of.

This is the current script I am working with.

import matplotlib.pyplot as plt
import numpy as np
#from PIL import Image
#import matplotlib.image as mpimg

def set_size(w,h, ax= None):
    """w, h: width, height in inches"""
    if not ax: ax=plt.gca()
    l = ax.figure.subplotpars.left
    r = ax.figure.subplotpars.right
    t = ax.figure.subplotpars.top
    b = ax.figure.subplotpars.bottom
    print(l,b,r,t)
    figw = float(w)/(r-l)
    figh = float(h)/(t-b)
    ax.figure.set_size_inches(figw, figh)
    
#Establishing axis limits
xlabel = "Distance (IN)"
xmin=1800
xmax = 3100 #  20 * 100
xstep = 100
xscale = np.arange(xmin, xmax   xstep, xstep)

ylabel = "Velcocity (M/S)"
ymin=0
ymax = 1.0 # .1 *20
ystep = .1
yscale = np.arange(ymin, ymax   ystep, ystep)
   
#fig, ax=plt.subplots(dpi = 102.4)#For 22in @ 1080p
fig, ax=plt.subplots(dpi = 163)#For 27in @ 4k
#Without removing the margins the scale is off. 
#If the margins could be measured and accounted for then there would be 
#little they could have a value.
plt.subplots_adjust(.04,.05,.96,.95)
plt.margins(x = 0, y = 0) 


#Having issues with the graph scaling
#fig.tight_layout()

ax.set_xticks(xscale)
ax.set_yticks(yscale)

ax.set_xlim(xscale[0], xscale[-1])
ax.set_ylim(yscale[0], yscale[-1])

#ax.plot([0,1,2,3,4,5],[0,1,2,3,4,5])
ax.plot([1900,2100,2400,2700],[.1,.2,.3,.4])

plt.xlabel(xlabel)
plt.ylabel(ylabel)

plt.grid()

set_size(len(xscale)-1, len(yscale)-1)

fig.savefig('plot.pdf')#, bbox_inches = 'tight')
fig.savefig('plot.png')#, bbox_inches = 'tight')
plt.show()

#im = Image.open('axis_ticks_cm.png')
#im.show()

# im = mpimg.imread('axis_ticks_cm.png')
# imgplot = plt.imshow(im)
# plt.show()

I don't know my way around figure and axis objects yet. So the code likely looks like it was haphazardly assembled- which it was. A lot of try and error but I'm figuring it out.

Axis Scaling References: Axes class - set explicitly size How do you change the size of figures drawn with Matplotlib?

CodePudding user response:

I have found a solution that works for me. As mentioned in the comments of my questions the Windows scaling factor plays a role in the a gui's size regardless of dpi. Taking this into account by multiplying the dpi by say 100/150 for a 150% scaling factor resolves the issue I had on the 4k screen. I did notice on a 1080p screen this scaling factor does not apply.

The standard plt.show() function seems to work well so long as there is enough room on the screen to present the plot, otherwise it will scale down.

I did figure out a way to lock the resolution in by using the tkinter library. By simply getting the image resolution, and then setting the tkinter gui to that size. Then setting image as the background. The window can of course be locked so it cannot be scaled or stretched. Even if the image is larger than the screen it will not scale window fit which is exactly what I need. I've included my code below.

import tkinter as tk
from PIL import Image

window = tk.Tk()

window.title("Image Viewer")

backPath = 'plot.png'
img = Image.open(backPath)
w, h = img.size

window.resizable(width = False, height = False)
window.geometry(str(w)   'x'   str(h))

background_image = tk.PhotoImage(file = backPath)
background_label = tk.Label(window, image=background_image)
background_label.place(x=0, y=0)

window.mainloop()
  •  Tags:  
  • Related