How do I scale mplfinance graph within Tkinter? - python

With the help of my post earlier, I have managed to turn my chart into a candlestick one. However I cannot seem to adjust the size of it.
Old chart:
New Chart:
I'd like to resize it to how it was before. I have tried adding the following to rcparams but it had no effect:
"figure.figsize": figure_size,
"savefig.bbox": "tight"
My old relevant code:
figure = plt.Figure(figsize=(0.7 * res_width / 100, 0.45 * res_height / 100), facecolor=BACKGROUND_COLOUR)
ax = figure.add_subplot(111, fc=BACKGROUND_COLOUR)
figure.tight_layout()
figure.subplots_adjust(left=0.05, right=1.0, bottom=0.0, top=1.0)
FigureCanvasTkAgg(figure, self).get_tk_widget().place(relx=0.02, rely=0.27)
My current code:
market_colours = mpf.make_marketcolors(up="g", down="r",
edge=background_colour,
wick=line_colour)
style_dict = {"xtick.color": line_colour,
"ytick.color": line_colour,
"xtick.labelcolor": text_colour,
"ytick.labelcolor": text_colour,
"axes.spines.top": False,
"axes.spines.right": False,
"axes.labelcolor": text_colour}
style = mpf.make_mpf_style(marketcolors=market_colours,
facecolor=background_colour,
edgecolor=line_colour,
figcolor=background_colour,
gridcolor=line_colour,
gridstyle="--",
rc=style_dict)
figure, ax = mpf.plot(df, type="candle", returnfig=True, style=style, TEXT_COLOUR))
FigureCanvasTkAgg(figure, self).get_tk_widget().place(relx=0.02, rely=0.27)
When trying .pack(expand=True) on the widget it also doesn't work.
Edit:
Thanks to Mr Goldfarb I have got the graph to be bigger, but it still does not fit right. Is there a way I can apply the figure.tight_layout() along with figure.subplots_adjust(left=0.05, right=1.0, bottom=0.0, top=1.0) that I usually add?

You can adjust the figure size with kwarg figsize=(width,height) in your call to mpf.plot(). Instead of:
figure, ax = mpf.plot(df, type="candle", returnfig=True, style=style, TEXT_COLOUR)
Try
figure, ax = mpf.plot(df, type="candle", returnfig=True, style=style, TEXT_COLOUR,
figsize=(0.7*res_width/100, 0.45*res_height/100) )
Regarding Figure.tight_layout() and Figure.subplots_adjust() ... mplfinance uses matplotlib's Figure.add_axes() to create Axes objects, and apparently, although add_axes() is part of matplotlib, the Axes that are created by add_axes() are incompatible with matplotlib's tight_layout. I do not know if subplots_adjust() will work either (as I've never tried it).
That said, mplfinance implements it's own tight_layout. Just set kwarg tight_layout=True when calling mpf.plot(). Try that first, but if that doesn't satisfy what you are trying to accomplish, then try using the scale_padding kwarg.

Related

plt.figure not resizing figure

I have this function and I want to change the size of the figure, however whatever values I put in the figsize, the figure size does not change. Can anybody suggest what's the problem? or if there is an alternative way for doing this?
def plot_comparison_barplots(df, bar_col, hue_col, scaled):
fig = plt.figure(figsize=(12,10))
fig.set_tight_layout(True)
plt.rcParams.update({'font.size': 9})
ax = sns.catplot(x=bar_col, y='count in %', data=df, hue=hue_col, kind='bar', order=scaled)
There is an easier way to implement this function, by using subplots instead of figure, as when you use the set_tight_layout() method, this automatically changes the location of the axes to make your graph look nicer, and make sure that none of the axis names are cut off. The quickest way of getting around this is to define your axes before the set_tight_layout() method, so that the figsize parameter overrides it.
Change:
fig = plt.figure(figsize=(12,10))
to
fig, ax = plt.subplots(figsize=(12,10))
You can add through Seaborn as:
sns.set(rc={'figure.figsize':(12,10)})

Python Matplotlib: How to disable Constrained Layout but keep the axes position?

I've created a (3,2) subplots and forced them in constrained_layout=True.
Then I wanted to disable the constrained_layout with .set_constrained_layout(False) due to performance issues, but I 'd like to keep the axes positions.
I tried to get the positions in constrained layout state, and then apply these positions to the axes after setting constrained_layout to False, following these instructions, but it doesn't work.
With the code below, I expected to obtain the following figure, but I ended up with the one below it.
What am I missing?
import matplotlib.pyplot as plt
fig, ax = plt.subplots(3,2,constrained_layout =True)
mng = plt.get_current_fig_manager()
mng.window.showMaximized()
fig.canvas.draw()
bounds = [ex.get_position().bounds for ex in fig.axes]
fig.set_constrained_layout(False)
for i in range(len(fig.axes)):
fig.axes[i].set_position(bounds[i])
fig.canvas.draw()
Is it wrong to adjust the vertical and horizontal in the subplot?
fig, ax = plt.subplots(3,2)
fig.subplots_adjust(wspace=0.3, hspace=0.3)

Using pyplot from Plots.jl. How to make several subplots have only one colobar?

I am using Plots.jl to make several plots in the same figure. When using the pyplot backend, each plot has it's own colorbar, which I don't want as they have the same data. I am trying to replicate the answer from this question, however I don't know in detail of the machinery under the Plots.jl API, so I haven't been able to replicate it. My plot is done as:
using Plots;pyplot()
p1 = plot(a,st=:contour,fill=true)
p2 = plot(b,st=:contour,fill=true)
p = plot(p1,p2)
And, the answer (which is in python) from the link is this:
fig, axes = plt.subplots(nrows=2, ncols=2)
for ax in axes.flat:
im = ax.imshow(np.random.random((10,10)), vmin=0, vmax=1)
fig.subplots_adjust(right=0.8)
cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7])
fig.colorbar(im, cax=cbar_ax)
plt.show()
As far as I understand, the code inside the for is actually making the plots in the axes created by plt.subplots (in my case this is done by Plots.jl
The next line makes the plots closer, and then the line fig.add_axes creates a new axis for the colorbar.
Finally, the line of fig.colorbar creates a colorbar in the new axis and uses the data from the last plot in the for loop.
My current code is:
cbar_ax = p.o[:add_axes]([0.85, 0.15, 0.05, 0.7]);
p.o[:colorbar](p.o[:axes][1][:contourf],cax=cbar_ax)
display(p)
And it doesn't work (I wouldn't expect it to work because I don't know what I'm doing.
The error I get is:
AttributeError("'function' object has no attribute 'autoscale_None'")
Which makes me think p.o:axes[:contourf] is not the way to summon what I am trying to.
Can anyone help out? Thanks
In general, if you want to use code on the PyPlot object it's better to just use PyPlot and forget about Plots. The mix rarely works in practice.
If you do want to use Plots you should be able to do
using Plots;pyplot()
lims = extrema([a;b])
p1 = plot(a,st=:contour,fill=true, colorbar = false)
p2 = plot(b,st=:contour,fill=true, colorbar = true, clims = lims)
p = plot(p1,p2)
One of the subplots will be much wider than the other - you probably need to adjust with #layout to get them the same width.

xlabel and ylabel out of plot region, cannot show completely in the figure

As can be seen in the figure, the xlabel and ylabe is out of plot region and can not show fully.
Someone may say change the fontsize, but I want the fontsize to be large.
below is the code:
from numpy import *
from pylab import *
tduration=3600
if tduration<960:
time=linspace(0,tduration,120)
else:
n=(tduration-960)/480
time1=linspace(0,960,8,endpoint=False)
time2=linspace(960,tduration,n)
time=hstack((time1,time2))
timemin=time/60
T0=20
Tf=T0+345*log10(8*timemin+1)
timetem=column_stack((timemin,Tf))
savetxt("timetem.txt",timetem,newline='\r\n',fmt='%f')
heatingRate=345/(8*timemin+1)
fig,ax1 =subplots()
ax2 = ax1.twinx()
rc('font',family='Times New Roman')
ax1.plot(timemin,Tf,'k',linewidth=3,label='ISO834 fire curve')
ax2.plot(timemin,heatingRate,'b--',linewidth=3,label='heating rate')
ax1.plot(0, 0,'b--', label = 'heating rate',linewidth=3)
leg=ax1.legend(loc='best',fontsize=24)
leg.get_frame().set_alpha(0.0)
ax1.set_ylabel(r"T$(^{\circ}C)$",fontsize=24,fontname="Times New Roman")
ax2.set_ylabel(r"Heating rate($^{\circ}C$/min)",fontsize=24,fontname="Times New Roman")
ax1.set_xlabel("Time(min)",fontsize=24,fontname="Times New Roman")
ax1.tick_params(labelsize=24)
ax2.tick_params(labelsize=24)
ax1.grid()
show()
fig.savefig('iso834 with hr.png', transparent=True)
It might be a bit late right now, but anyway:
You should specify the inner margins for your figure and the spaces within subplots, if you have any subplots in your figure. Following code will help you. Put it right before showing the plot.
plt.subplots_adjust(wspace=0.6, hspace=0.6, left=0.1, bottom=0.22, right=0.96, top=0.96)
But, another question would be how to specify the values for above parameters in subplot_adjust, then the answer is to use subplot_tool. Put following code right before showing the plot and a popup window comes up and you can play with the values and find the one you like.
plt.subplot_tool()
Also, it is better to specify the total size of your figure using the figsize argument.
I hope it helps.

Hiding axis text in matplotlib plots

I'm trying to plot a figure without tickmarks or numbers on either of the axes (I use axes in the traditional sense, not the matplotlib nomenclature!). An issue I have come across is where matplotlib adjusts the x(y)ticklabels by subtracting a value N, then adds N at the end of the axis.
This may be vague, but the following simplified example highlights the issue, with '6.18' being the offending value of N:
import matplotlib.pyplot as plt
import random
prefix = 6.18
rx = [prefix+(0.001*random.random()) for i in arange(100)]
ry = [prefix+(0.001*random.random()) for i in arange(100)]
plt.plot(rx,ry,'ko')
frame1 = plt.gca()
for xlabel_i in frame1.axes.get_xticklabels():
xlabel_i.set_visible(False)
xlabel_i.set_fontsize(0.0)
for xlabel_i in frame1.axes.get_yticklabels():
xlabel_i.set_fontsize(0.0)
xlabel_i.set_visible(False)
for tick in frame1.axes.get_xticklines():
tick.set_visible(False)
for tick in frame1.axes.get_yticklines():
tick.set_visible(False)
plt.show()
The three things I would like to know are:
How to turn off this behaviour in the first place (although in most cases it is useful, it is not always!) I have looked through matplotlib.axis.XAxis and cannot find anything appropriate
How can I make N disappear (i.e. X.set_visible(False))
Is there a better way to do the above anyway? My final plot would be 4x4 subplots in a figure, if that is relevant.
Instead of hiding each element, you can hide the whole axis:
frame1.axes.get_xaxis().set_visible(False)
frame1.axes.get_yaxis().set_visible(False)
Or, you can set the ticks to an empty list:
frame1.axes.get_xaxis().set_ticks([])
frame1.axes.get_yaxis().set_ticks([])
In this second option, you can still use plt.xlabel() and plt.ylabel() to add labels to the axes.
If you want to hide just the axis text keeping the grid lines:
frame1 = plt.gca()
frame1.axes.xaxis.set_ticklabels([])
frame1.axes.yaxis.set_ticklabels([])
Doing set_visible(False) or set_ticks([]) will also hide the grid lines.
If you are like me and don't always retrieve the axes, ax, when plotting the figure, then a simple solution would be to do
plt.xticks([])
plt.yticks([])
I've colour coded this figure to ease the process.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
You can have full control over the figure using these commands, to complete the answer I've add also the control over the spines:
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# X AXIS -BORDER
ax.spines['bottom'].set_visible(False)
# BLUE
ax.set_xticklabels([])
# RED
ax.set_xticks([])
# RED AND BLUE TOGETHER
ax.axes.get_xaxis().set_visible(False)
# Y AXIS -BORDER
ax.spines['left'].set_visible(False)
# YELLOW
ax.set_yticklabels([])
# GREEN
ax.set_yticks([])
# YELLOW AND GREEN TOGHETHER
ax.axes.get_yaxis().set_visible(False)
I was not actually able to render an image without borders or axis data based on any of the code snippets here (even the one accepted at the answer). After digging through some API documentation, I landed on this code to render my image
plt.axis('off')
plt.tick_params(axis='both', left=False, top=False, right=False, bottom=False, labelleft=False, labeltop=False, labelright=False, labelbottom=False)
plt.savefig('foo.png', dpi=100, bbox_inches='tight', pad_inches=0.0)
I used the tick_params call to basically shut down any extra information that might be rendered and I have a perfect graph in my output file.
Somewhat of an old thread but, this seems to be a faster method using the latest version of matplotlib:
set the major formatter for the x-axis
ax.xaxis.set_major_formatter(plt.NullFormatter())
One trick could be setting the color of tick labels as white to hide it!
plt.xticks(color='w')
plt.yticks(color='w')
or to be more generalized (#Armin Okić), you can set it as "None".
When using the object oriented API, the Axes object has two useful methods for removing the axis text, set_xticklabels() and set_xticks().
Say you create a plot using
fig, ax = plt.subplots(1)
ax.plot(x, y)
If you simply want to remove the tick labels, you could use
ax.set_xticklabels([])
or to remove the ticks completely, you could use
ax.set_xticks([])
These methods are useful for specifying exactly where you want the ticks and how you want them labeled. Passing an empty list results in no ticks, or no labels, respectively.
You could simply set xlabel to None, straight in your axis. Below an working example using seaborn
from matplotlib import pyplot as plt
import seaborn as sns
tips = sns.load_dataset("tips")
ax = sns.boxplot(x="day", y="total_bill", data=tips)
ax.set(xlabel=None)
plt.show()
Just do this in case you have subplots
fig, axs = plt.subplots(1, 2, figsize=(16, 8))
ax[0].set_yticklabels([]) # x-axis
ax[0].set_xticklabels([]) # y-axis

Categories

Resources