millejoh / emacs-ipython-notebook

Jupyter notebook client in Emacs
http://millejoh.github.io/emacs-ipython-notebook/
GNU General Public License v3.0
1.47k stars 123 forks source link

How to make inline plot size appropriate for a given screen DPI? #625

Closed notuntoward closed 4 years ago

notuntoward commented 4 years ago

Is there a way to inform EIN of the current screen dpi so that it can keep plots the same size across different computers?

In Jupyter notebook, inline matplotlib plots scale reasonably with changes in screen size and resolution; my work computer has a large 94 dpi screen while my Surface Pro has a little 185 dpi screen, yet plots are readable on either. Jupyter notebook is reading the screen dpi and uses it to keep plots a more or less constant number of inches tall and wide.

But EIN seems to render inline plots at a fixed number of pixels -- plots look fine on the 94 dpi screen and are unreadably small on the 185 dpi screen.

Is there an EIN variable or customization I can set that controls the number of pixels covered by a plot, or better yet, is there an EIN setting for dpi, so that EIN calculates the number of pixels iself?

millejoh commented 4 years ago

Are you sure it is jupyter - or is your browser making the dpi adjustment? In any case if you are using matplotlib the solution is relatively simple:

from matplotlib.pylab import rcParams

rcParams['figure.dpi'] = 120 # Or whatever value makes your graphs look good.
notuntoward commented 4 years ago

Yes, you're right that it's the browser doing the pixel scaling.

Thanks for the info about rcParams, but I'm trying to avoid putting the image adjustment code in the .ipynb file -- I'll be sharing notebooks with coworkers who use different machines, and who don't use emacs.

So instead, I'd like to control the scaling from my .emacs file. Somewhere, EIN or a library it calls, sets the pixel size of the inline plot images. My goal is to intercept that setting, and insert a DPI-appropriate number of pixels. I'm doing that in my .emacs for other emacs bits that scale poorly, but I can't find the hook or customization for EIN.

Is there one, or could there be?

millejoh commented 4 years ago

You can try customizing the variable image-scaling-factor. Note I found this variable fairly quickly after doing a google search for emacs image scaling.

You can also configure your particular jupyter install to load some custom code every time you open a notebook. I leave determining the details of doing this as homework.

notuntoward commented 4 years ago

I tried image-scaling-factorbut unfortunately, it had no effect on the image size. Do you know where EIN sets the plot size in pixels? I grepped through the source and couldn't find it.

millejoh commented 4 years ago

I was thinking more along the line of configuring your particular kernel to run some code setting the image dpi. If image-scaling-factor doesn't work then there probably is no way of doing this directly in emacs, it must be done from inside Python.

I can write a short helper function for doing this. I'll get it merged in a bit, assuming I don't break travis (which I am quite good at).

notuntoward commented 4 years ago

OK, thanks! I'll give it a try.

Just to be sure that I understand, are you saying that the inline plot "number of pixels" is entirely controlled by Jupyter; that it's getting that wrong on high DPI screens; but that the browser detects and fixes the error?

Or alternatively, is it the case that EIN and the browser are talking to different chunks of Jupyter, and it's only the chunk that EIN talks to that makes the "number of pixels" error, and that the browser is merely displaying what it's given?

EDIT: Oh waitaminute, following your link, I just realized that EIN may not be talking to Jupyter at all; it's talking to ipython.

I'm new to EIN, Python and Jupyter all at the same time. I'm also trying to get elpy running on Windows, and one of the big progress steps was, as I understand it, to replace ipython with Jupyter. Maybe Jupyter then calls iconsole? Anyway, since Jupyter & the browser are somehow correctly sizing images, would EIN be borrow that trick?

No idea what I'm talking about. Just thought I'd mention it.

millejoh commented 4 years ago

Display scaling is sort of a complicated topic. Not so much because the concept is difficult to understand, but understanding who is doing it and when is. I'm going to stop myself here as this is turning into a deep, deep rabbit hole. This issue also seems to happen in the browser interface under the right conditions. It sounds like image scaling is occurring in the javascript that drives the Jupyter notebook browser interface. I'm too lazy to figure out that all works, but I did write an off-the-cuff helper function that may or may not help you out.

After I merge in #627, check out ein:pytools-matplotlib-api-correction. For the code to work you need to first call %matplotlib inline in your notebook, as calling this magic will change the dpi setting (don't ask me why).

dickmao commented 4 years ago

ein:output-area-inlined-images defaults to nil (for now), and so plots should appear outside emacs (like in ESS). Thus you can customize however you wish plots to look independent of EIN.

spartacoos commented 3 years ago

Hi, has anyone figured out a way to make the plots "auto-tune" the dpi settings to look good within emacs? image