In Visual Studio Code, how can I efficiently tweak Pyplot figures? - python

Often I need to optimize a complex plot in many iterations, an example would be finding a good position for the legend. Let's say my code looks something like this:
def main()
...
plot(x, y)
def plot(data, legends)
fig, ax = subplots(1,2)
...
ax[0].legend(frameon=False,loc="lower right")
Now I need to run the last line multiple times with different locations and look at the resulting figure. Currently, how I do this would be to set a breakpoint after that last line, start debugging until it pauses at the breakpoint, and then I will iteratively run ax[0].legend() with different arguments followed by fig.savefig(path) in the debug console. The result can be seen in an image viewer. Is there a quicker, "real time" way to do this task? Is there a VS Code shortcut for "Run selected code in Debug Console" maybe? Edit: it is possible to assign this shortcut, its name in the list of key bindings is Evaluate in Debug Console.

Related

Need to force display of figures and close as needed during running of code

I have a python code that plots several figures. The relevant parts are
import matplotlib.pyplot as plt
plt.ion()
for p in range(np):
for g in range(ng):
figs = []
for n in range(ns):
figs.append(plt.figure())
gsg = # object I am working with
cg = plt.contourf(gsg.x, gsg.y, gsg.u[:,:])
cb = plt.colorbar()
figs[n].suptitle(title)
print title, gsg.u[ex_index,ex_index,:]
go_ahead = raw_input()
For certain cases, I can't run this straight through and just look at all the figures because too many figures are produced and python starts automatically closing several of them.
So what I want is for that inner loop to plot ns figures, then I pause the execution (hence the go_ahead input), look at the displayed figures, close them on the screen, and let the code go to the next batch. I can't figure out how to make this work.
The closest I have come is by putting plt.show(block=True) command after figs[n].suptitle(). This does result in the display of a figure during run time, but I can only see one figure at a time. plt.show() and plt.show(block=False) does not result in any display at all, until the end of execution, which is what I am trying to avoid.
Any ideas?

Python ggplot: Is it possible to turn off the GUI displayed? and get a command-line ("non-interactive plotting"/"batch")

When plotting with Python ggplot, every single plot command causes a GUI pane to be displayed and suspend execution ("interactive plotting"). But I want to:
avoid/ turn off this GUI and save the plot object some where in runtime (I will be displaying it in some other C# forms control).
find a Python equivalent to dev.off() command in R language which turns off the GUI for plotting.
Example:
print ggplot(data, aes('Age', 'Weight')) + geom_point(colour='steelblue')
When I execute this, it opens up a new GUI (like below) displaying the plot.
You can do the following, which returns a matplotlib figure:
g = ggplot(...) + geom_xxx(...)
fig = g.draw()
ggplots __repr__() method (what is called by print(g) is basically self.draw() then use matplotlibs plt.show() to show the plot...
You can also use ggsave(g) to save the plot somewhere.
Since plotting is triggered by __repr__ method the obvious approach is to avoid situations when it is called. Since you want to use this plot in some other place there is no reason to call print or even executing statements which will be discarded like this:
ggplot(data, aes('Age', 'Weight')) + geom_point(colour='steelblue')
Instead you can simply assign it to the variable
p = ggplot(data, aes('Age', 'Weight')) + geom_point(colour='steelblue')
what is exactly the same thing one would do in R. Using graphic device to redirect output and discarding it doesn't really make sense.
If for some reason that's not enough you switch to non-interactive matplotlib backend:
import matplotlib
matplotlib.use('Agg')
from ggplot import *
ggplot(aes(x='date', y='beef'), data=meat)
<ggplot: (...)>

Is there a better way to re-use plots Matplotlib?

The below code block (A) solves my overall problem of being able to re-use plots, but i'm wondering if there is a better way (one that doesn't involve creating a function for each plt.plot, as is shown below.
Code block A:
import maptplotlib.pyplot as plt
#create a function just to call the plt.plot
def first_plot(): plt.plot(x,y)
first_plot()
# Now i can just show the first plot
plt.show()
def second_plot(): plt.plot(x,z)
first_plot() # instead of plt.plot(x,y)
second_plot() # instead of plt.plot(x,z)
# now i can show both plots
plt.show()
if the plots are complicated:
plot.plot(lots of details)
and their are many:
plots = [first,second,third,fourth,...]
I would think this would be advantageous because it avoids code re-use.
However, creating a function just to call plt.plot() indicates to me their might be a better way.what i would like to be doing is something like
first_plot = plt.plot(x,y)
first_plot()
#now i want to show just the first plot
plt.show() # first call
second_plot = plt.plot(x,z)
# now i want to show them together combined
first_plot()
second_plot()
plt.show() # second call
But this doesn't seem to work/e.g the second call to plt.show() wouldn't produce the first plot. (even if you unpack first_plot (which in reality, from code block B, is actual a list):
In [17]: first_plot
Out[17]: [<matplotlib.lines.Line2D at 0x7fd33ac8ff50>]
This cannot be used to produce the plot again in anyway I can see. This might be because of the relationship between plt.show and plt.plot, which i don't fully understand. Plt.plot seems to put the plot in a que, that then plt.show pops out. However,
plt.shows description talks about a blocking and unblocking mode and interactive and non-interactive mode:
show(*args, **kw)
When running in ipython with its pylab mode, display all
figures and return to the ipython prompt.
In non-interactive mode, display all figures and block until
the figures have been closed; in interactive mode it has no
effect unless figures were created prior to a change from
non-interactive to interactive mode (not recommended). In
that case it displays the figures but does not block.
A single experimental keyword argument, *block*, may be
set to True or False to override the blocking behavior
described above.
Which i don't understand. But regardless of how i call plt.show() vs plt.show(False) (blocking?) it doesn't seem to have an impact e.g the output is the same in the context of code block A and B.
So put another way, is there a way to select which plots created to show/overlay at different points in the code?
However awkward, it seems the best way to "re-use" plots as described in my question is to do as I original suggested and put it inside a function.
def some_plot(): return plot(x,y)
and then if you want to re-use the plot simply call the function again:
some_plot()

ipython notebook pylab fig size running twice?

I am using iPython notebook wo do some visualization. Figures are inline (the profile defaults to interactive, as this supports a number of users who prefer interactive more frequently):
%pylab inline
Using the inline plot, I often set the fig size manually:
figsize(10,5)
I find that I need to run cells twice to realize a change in the fig size. For example, if I define cell [1] as figsize(10,5) and run it, the output is the correct size. If I then run cell [2] with `fig size(5,10)1 I get output that is of size (10,5). A second run of cell [2] draws correctly.
Any insight into why this is occurring? Is it due to the inline backend and I just need to live with it?
Thanks.
Definition: figsize(sizex, sizey)
Docstring:
Set the default figure size to be [sizex, sizey].
This is just an easy to remember, convenience wrapper that sets::
matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
This seem correct to me, if you run the following, whatever value of X, Y I always get the right plot
figsize(10,5)
plot(range(10))
if you run it after your plot, then you set the default for next plot... but without exact example, hard to say..

How to disable screen update in matplotlib

I have a loop that is adding a line to a plot on each iteration. Right now this is horribly slow as it seems to redraw the the whole graph each time. Is it possible to disable screen updates for a graph while it is being set up then re-enable them afterwards.
Here's the code:
for rr,dd in zip(angles,dists):
if dd == inf:
pass
else:
lineend = (array([cos(rr), sin(rr)]) * dd)+origin;
plot([origin[0], lineend[0]], [origin[1], lineend[1]],'-b');
I know I should just combine this all into one call to plot and I'll probably do it for this example. But there are other bits where that would be more of a problem so a general solution would be really helpful.
Thanks!
It sounds like you have the interactive mode on, so you should just set it to off using the command
ioff()
Note that when interactive mode is off, you'll need to use the command show() to display the plots.

Categories

Resources