tight_layout() for FigureCanvasTkAgg - matplotlib

I need to add 2 subplots in a canvas. Im trying to use FigureCanvasTkAgg as the plots need to be 3-D interactive. Is there any equvivalent of tight_layout feature available in canvas/FigureCanvasTkAgg ? Tried FigureCanvasTkAgg.tight_layout() and gives error..
f = Figure(figsize=(5,3), dpi=100)
a = f.add_subplot(121)
a.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a1 = f.add_subplot(122)
a1.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
canvas = FigureCanvasTkAgg(f, self)
canvas.show()
canvas.tight_layout()
canvas.get_tk_widget().grid(row=20,column=6,sticky=W)

Using fig = Figure(tight_layout=True) solved the problem mentioned by #James Brown where the figure is taken to the edge in my case (Windows 10, Python 3.8.3, Matplotlib 3.2.2).

Understood with some trials. tight_layout() is associated with the Figure and not the backend.
f.tight_layout() inserted before canvas declaration solves the issue

I wanted to set my own setting because tight_layout take it to edge of the frame. I used the toolbar to get my numbers and place this before the canvas.
f.subplots_adjust(left=0.06, bottom=0.16, right=0.90, top=0.92, wspace=0.21, hspace=0.67)

Related

How to Superimpose on Matplotlib

I want to draw a triangle with two points inside using matplotlib. Here is the code I'm using:
plt.figure()
triangleEdges = np.array([[0,0],[1,0],[0.5,0.5*np.sqrt(3)]])
colors = ['red', 'green', 'blue']
t1 = plt.Polygon(triangleEdges, facecolor="none",
edgecolor='black', linewidth=2)
t1.set_facecolor('xkcd:salmon')
plt.gca().add_patch(t1)
drawSoftmaxPoint('blue',100,np.array([0.2,0.1,0.7]) )
drawSoftmaxPoint('red',100,np.array([0.5,0.1,0.7]))
plt.show()
Picture
According to the code, there should be two points inside the triangle, but it looks like the background is covering them. How can I make them visible?
Thank you!
you could use alpha and z-order in your polygon to make it happen (from the doc of matplotlib). just try to set the alpha value between 0 and 1 to check if you can see your points. and then maybe use z-order on your different elements to make sure the fill of the polygon is deepest (most behind). example of zorder:
https://matplotlib.org/gallery/misc/zorder_demo.html

How to remove marker edges in seaborn.pairplot()?

Seaborn has a handy function pairplot to create a matrix of scatter plots. Unfortunately, some standard matplotlib commands don't work with it.
sns.pairplot(matrix[cols[:4]].head(100), plot_kws=dict(alpha=.5, mew=0))
The markers get some ugly white edges. I tried mew for markeredgewidth keyword to remove them as it would be used in matplotlib, but that is an unknown property for seaborn. How can I remove these edges?
A scatter does not have a mew keyword. It is edgecolor instead. Hence
sns.pairplot(data, plot_kws=dict(edgecolor="none"))
would remove the white edge around the scatterpoints.
ImportanceOfBeingErnest's answer is much more precise. Alternatively, you can also use a workaround: Set the color of choice for both the face and the edges of the markers as (example from the docs)
import seaborn as sns
sns.set(style="ticks", color_codes=True)
iris = sns.load_dataset("iris")
g = sns.pairplot(iris, plot_kws=dict(facecolor='b', edgecolor="b"))
EDIT based on comments below IOBE's answer: Just specifying the linewidth=0 also works the same way on markers as specifying edgecolor="none".
g = sns.pairplot(iris, plot_kws=dict(linewidth=0))

Offset text position in matplotlib [duplicate]

I'm losing my wits here with this 'simple' problem:
In the colorbar (illustrated in picture) in matplotlib I need to move offsetText (base multiplier) from top of the colorbar to bottom.
Code that I'm using for this plot is (using gridspec):
f.add_subplot(ax12)
ax10 = plt.Subplot(f, gs00[1, 0])
cb = plt.colorbar(h3,cax=ax10)
cb.formatter.set_scientific(True)
cb.formatter.set_powerlimits((0,0))
cb.ax.yaxis.offsetText.set(size=6)
cb.update_ticks()
ax10.yaxis.set_ticks_position('left')
ax10.tick_params(labelsize=6)
f.add_subplot(ax10)
Thanks in advance!
(Btw, Python version = 2.7.6, matplotlib version = 1.3.1 - upgrading currently not an option until I finish current project)
It's in general not possible to change the position of the offsetText label. This would still be an open issue.
A solution can therefor be to overwrite the yaxis' _update_offset_text_position method to position the offsetText on the bottom of the yaxis.
import matplotlib.pyplot as plt
import types
def bottom_offset(self, bboxes, bboxes2):
bottom = self.axes.bbox.ymin
self.offsetText.set(va="top", ha="left")
self.offsetText.set_position(
(0, bottom - self.OFFSETTEXTPAD * self.figure.dpi / 72.0))
fig, ax = plt.subplots()
im = ax.imshow([[1e5,2e5],[0.1e5,1e5]])
cb = plt.colorbar(im)
cb.formatter.set_scientific(True)
cb.formatter.set_powerlimits((0,0))
def register_bottom_offset(axis, func):
axis._update_offset_text_position = types.MethodType(func, axis)
register_bottom_offset(cb.ax.yaxis, bottom_offset)
cb.update_ticks()
plt.show()
If the colorbar is positioned on the left side of the plot the following might look better:
self.offsetText.set(va="top", ha="right")
self.offsetText.set_position(
(1, bottom - self.OFFSETTEXTPAD * self.figure.dpi / 72.0))
Hmmm... Apparently, it's not possible to move colorbar's scientific base multiplier up or down, just slightly left or right.
Workaround would be to hide it and just add (same) custom text that would be positioned at the bottom (in my case):
cb.ax.yaxis.get_offset_text().set_visible(False)
cb.ax.text(0.5, -0.1, '1e4', va='bottom', ha='center', size=6)
If someone has more elegant solution, I would be happy to see it!

%matplotlib inline rescale figure after xlim / ylim on hist2d plot [duplicate]

I'm trying to conciliate dots annotation in a Matplotlib scatter plot with a manual limit setting, but I either got an error message or I get a design problem.
Here is my code :
fig, ax = plt.subplots(figsize = (20,10)) #manual limit setting
plt.axis([-2,3,-2.5,5])
plt.scatter(x, y)
for i, txt in enumerate(n): #dot annotation
ax.annotate(txt, (x[i], y[i]))
Here is a screen cap of the output (I got the final scatter plot as a small rectangle located in the left corner of a big white rectangle :
I tried this also :
fig, ax = plt.subplots(figsize = (20,10))
ax = plt.axis([-2,3,-2.5,5])
plt.scatter(x, y)
for i, txt in enumerate(n):
ax.annotate(txt, (x[i], y[i]))
But of course I got the following error message (even though the chart correctly displays, but without the labels next to each corresponding dot).
AttributeError: 'list' object has no attribute 'annotate'
The error arises because my loop tries to iterate through ax = plt.axis([-2,3,-2.5,5]), which doesn't make sense indeed.
Any solution to overcome this issue ?
Thank you
The problem occurs because of the special casing of texts when it comes to clipping. Usually you might want text outside the axes to be shown. Therefore annotations and text have a annotation_clip argument. However, this interferes with the bbox_inches="tight" option when saving annotations, because the annotations is then still considered part of the layout and hence the figure takes annotations outside the axes still into account.
Two solutions:
Set annotation_clip and clip_on. I.e. You may explicitely tell the annotation to clip at the axes:
ax.annotate(txt, (x[i], y[i]), annotation_clip=True, clip_on=True)
Set bbox_inches to None. When using the IPython inline backend you can tell it not to expand the figure via
%config InlineBackend.print_figure_kwargs = {'bbox_inches':None}
in a cell before starting to create your content. (This is seen in this answer)
I can't replicate the first issue (tried in versions 2.2.3, 3.1.1, 3.1.2) - I get this (using random data). Try upgrading your version of matplotlib or using
plt.savefig('/path/to/output/image.png')
To save the figure to the disk instead of showing it directly and see if the problem persists.
I can however explain the error
AttributeError: 'list' object has no attribute 'annotate'
This occurs because plt.axis() returns [xmin, xmax, ymin, ymax], not an axes instance (fig, ax = plt.subplots(figsize=(20,10) returns an axes instance to ax).

PyPlot in Juno: Fixing axis height

I apologise if this has already been asked, I've searched long and hard on this site and couldn't find anything that worked. I'm using Julia, specifically the Juno IDE, and I am trying to use PyPlot to create my graphs. I wanted to set the y axis height when plotting, but leave the x axis variable. Here is the code I have been using to generate my plots
fig = figure()
ax = fig[:add_axes]
BEFE250 = (plot(s1, s2, lw=1.0, "-", color="b"))
ylabel("u(x,t)", size=20)
xlabel("t", size=20)
gcf()
which gives me
However, I need space in the top left corner as I am going to layer another picture on top in latex. So I need to set the y-axis height to between -3 and 3. However, if I set the axes height in PyPlot
fig = figure()
ax = fig[:add_axes]([0.1, 0.1, -3.0, 3.0])
BEFE250 = (plot(s1, s2, lw=1.0, "-", color="b"))
ylabel("u(x,t)", size=20)
xlabel("t", size=20)
gcf()
then it switches the orientation of the x-axis. If I set the axis height after running the plot, PyPlot puts the picture in a box in a legend off to the side of the main picture, and the main picture is empty? If someone could help me out it would be greatly appreciated.
Thanks for your help.
EDIT: Using xlim=(-10.,10.) and ylim=(-2.,12.) doesn't work either. PyPlot still adapts the axes to the data.
Try xlim(-10, 10) and ylim(-2, 12) after the plot command:
plot(s1, s2, lw=1.0, "-", color="b")
ylim(-3, 3)
Just try this, without the add_axes.
You probably also want LaTeX labels -- just add an L before the string, which gives a special LaTeX string from the LaTeXString package. You can either just add the L, or add $ inside too:
ylabel(L"u(x,t)", size=20)
ylabel(L"$u(x,t)$", size=20)
[The $ are necessary in certain circumstances that I forget.]
I'm not sure how good the PyPlot support is in Juno.
You might want to try this in IJulia.
By the way, is there a reason you want to layer on a separate figure in LaTeX? That might not be the best way to do it.