Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Description
Bug summary
I need to label a lot of elemental emission peaks on X-ray spectra. There are three series of peaks denoted K, L and M, so I put three axes above the plot. (This is the best approach I could find online, it does not seem that multiple text labels would be covered in the docs. I will be thankful for any tip.)
Anyway, the plotting then goes very very slow: roughly 4× slower when the number of labels doubles.
Code for reproduction
#!/usr/bin/python3#-*- coding: utf-8 -*-## Import common moduliimportmatplotlib,sysmatplotlib.use("cairo")# helps a bit#matplotlib.rc('text', usetex=False)importmatplotlib.pyplotaspltimportnumpyasnpfig,ax=plt.subplots(nrows=1,ncols=1,figsize=(16,10))x,y= [1,2,3], [5,6,4]## dummy data#x,y = np.ax.plot(x,y,marker='o')elem= ["H","He","Li","Be","B","C","N","O","F","Ne","Na","Mg","Al","Si","P","S","Cl","Ar","K","Ca","Sc","Ti","V","Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr","Rb","Sr","Y","Zr","Nb","Mo","Tc","Ru","Rh","Pd","Ag","Cd","In","Sn","Sb","Te","I","Xe","Cs","Ba","La","Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy","Ho","Er","Tm","Yb","Lu","Hf","Ta","W","Re","Os","Ir","Pt","Au","Hg","Tl","Pb","Bi","Po","At","Rn","Fr","Ra","Ac","Th","Pa","U","Np","Pu","Am","Cm","Bk","Cf","Es"][:int(sys.argv[1])iflen(sys.argv)>1else1000]max_x=14use_math=Falseifmax_x:ax.set_xlim(xmin=0,xmax=max_x)posK=np.arange(len(elem))**2*3/4*0.0136# a bit inaccurate Moseley law for K-seriesax2=ax.twiny()ax2.plot(x,y,color="None")ax2.set_xticks(posK)# (must precede set_xlim)ifuse_math:ax2.set_xticklabels((s+"$_K$"forsinelem),fontsize=8)else:ax2.set_xticklabels((s+"K"forsinelem),fontsize=8)# helps a bitifmax_x:ax2.set_xlim(xmin=0,xmax=max_x)posL=np.arange(len(elem))**2*3/4*0.0136/3.9# very inaccurate Moseley law for L-seriesax3=ax.twiny()ax3.plot(x,y,color="None")ax3.set_xticks(posL)ifuse_math:ax3.set_xticklabels((s+"$_L$"forsinelem),fontsize=8)else:ax3.set_xticklabels((s+"_L"forsinelem),fontsize=8)ifmax_x:ax3.set_xlim(xmin=0,xmax=max_x)ax3.spines["top"].set_position(("axes",1.05))posM=np.arange(len(elem))**2*3/4*0.0136/9.9# very inaccurate Moseley law for M-seriesax4=ax.twiny()ax4.plot(x,y,color="None")ax4.set_xticks(posM)ifuse_math:ax4.set_xticklabels((s+"$_M$"forsinelem),fontsize=8)else:ax4.set_xticklabels((s+"_M"forsinelem),fontsize=8)ifmax_x:ax4.set_xlim(xmin=0,xmax=max_x)ax4.spines["top"].set_position(("axes",1.10))print('ready to output',flush=True)fig.savefig("output.png",bbox_inches='tight')
Actual outcome
By defaultQtAgg
is used. Withuse_math=True
it takes 1m59,698s, without it only 0m18,759s.
When I switch backend tocairo
: Withuse_math=True
it takes 1m30,385s, without it only 0m11,522s. Still a lot.
Expected outcome
Such a simple plot could render within few seconds, even if lower indices are used rendered using the $ ... $ notation.
Also, as aseparate minor bug, I can seefontsize=8
has applied on the first extra axis only. The other two would not change their font size even when explicitly asked for.
Additional information
This bug was observed also in Matplotlib 3.1.x taken from the Ubuntu repository. Today I checked out the devel version and it is basically the same.
Almost all the code runs within a second. The slow command is thesavefig
.
I don't know why this happens, it looks like if every next label somehow needed to "update" all existing ones; this would explain the quadratic dependence of time.
I don't know any fix.
Operating system
Ubuntu
Matplotlib Version
3.6.0.dev995+g21b76ae7f7
Matplotlib Backend
QtAgg by default,
Python version
Python 3.8.10 (default, Sep 28 2021, 16:10:42)
Jupyter version
N/A
Installation
git checkout