Latex tick label overlapping axis in graph generated by matplotlib - matplotlib

I am using the following code from the standard beginner's matplotlib tutorial.
from pylab import *
figure(figsize=(10, 6), dpi=80)
subplot(1,1,1)
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)
plot(X, C, color="blue", linewidth=2.5, linestyle="-",
label=r'Cosine')
plot(X, S, color="red", linewidth=2.5, linestyle="-",
label=r"Sine")
xlim(X.min()*1.1, X.max()*1.1)
ylim(C.min()*1.1, C.max()*1.1)
ax = gca()
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position('center')
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
[r'$-\pi$', r'$-\frac{\pi}{2}$',r'$0$', r'$\frac{\pi}{2}$',r'$+\pi$'])
yticks([-1, +1])
legend(loc='upper left')
for label in ax.get_xticklabels() + ax.get_yticklabels():
label.set_fontsize(20)
label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65))
show(block=False)
which results in the following graph
I've tried to figure out why the latex tick labels for pi/2 and -pi/2 are intersecting the x-axis, but I cannot find anything on Google, SO or in the matplotlib documentation. Is this potentially a bug? I'm on OSX Mountain Lion, Python 2.7.6, matplotlib 1.3.1, ipython 2.1.0.

Thanks to the comment by #Schorsch, I was able to narrow down the problem. It had to do with incompatibilities with two versions of libpng I had installed with Homebrew.
$brew info libpng
libpng: stable 1.6.12 (bottled)
http://www.libpng.org/pub/png/libpng.html
/usr/local/Cellar/libpng/1.5.17 (15 files, 1.3M)
Built from source with: --universal
/usr/local/Cellar/libpng/1.6.12 (17 files, 1.3M) *
It seems when I installed matplotlib with
pip install matplotlib
It used libpng 1.5.17, but when running ipython --pylab it was using 1.6.12. To force pip to use the appropriate version of libpng I used the following shell variables.
export LDFLAGS="-L/usr/local/Cellar/libpng/1.6.12/lib/ -L/usr/X11/lib"
export CFLAGS="-I/usr/local/Cellar/libpng/1.6.12/include/ -I/usr/X11/include -I/usr/X11/include/freetype2"
Then to reinstall matplot lib
pip install --upgrade --force-reinstall matplotlib
Then to ensure that latex rendering is used
from matplotlib import rc
rc('text', usetex=True)
Results in the proper figure

Related

Matplotlib fonts not found in Google Colab [duplicate]

Using custom fonts in matplotlib locally involves storing the .ttfs in the matplotlib/mpl-data/fonts/ttf/ folder, then calling mpl.font_manager._rebuild(), then setting mpl.rcParams['font.sans-serif'].
Is there any way to do this in Google Colaboratory, where it doesn't seem that this ttf folder is accessible?
For example, I'd like to use the Roboto font. After installing, this would be invoked using mpl.rcParams['font.sans-serif'] = 'Roboto'.
The ttf folder is here:
/usr/local/lib/python3.6/dist-packages/matplotlib/mpl-data/fonts/ttf
So you want to download the ttf there, e.g.:
!wget https://github.com/Phonbopit/sarabun-webfont/raw/master/fonts/thsarabunnew-webfont.ttf -P /usr/local/lib/python3.6/dist-packages/matplotlib/mpl-data/fonts/ttf
matplotlib.font_manager._rebuild()
matplotlib.rc('font', family='TH Sarabun New')
update 2019-12
_rebuild() no longer works. Here's another method which still works.
import matplotlib
import matplotlib.font_manager as fm
!wget https://github.com/Phonbopit/sarabun-webfont/raw/master/fonts/thsarabunnew-webfont.ttf
fm.fontManager.ttflist += fm.createFontList(['thsarabunnew-webfont.ttf'])
matplotlib.rc('font', family='TH Sarabun New')
Wanted to add a full, succinct answer that currently works.
# Download fonts of choice. Here we download Open Sans variants to
# the current directory.
# It's not necessary to download to the share or matplotlib folders:
# /usr/share/fonts/truetype
# /usr/local/lib/python3.6/dist-packages/matplotlib/mpl-data/fonts/ttf
!wget 'https://github.com/google/fonts/raw/master/apache/opensans/OpenSans-Regular.ttf'
!wget 'https://github.com/google/fonts/raw/master/apache/opensans/OpenSans-Light.ttf'
!wget 'https://github.com/google/fonts/raw/master/apache/opensans/OpenSans-SemiBold.ttf'
!wget 'https://github.com/google/fonts/raw/master/apache/opensans/OpenSans-Bold.ttf'
from matplotlib import font_manager as fm, pyplot as plt
# Pick up any fonts in the current directory.
# If you do end up downloading the fonts to /usr/share/fonts/truetype,
# change this to: fm.findSystemFonts()
font_files = fm.findSystemFonts('.')
# Go through and add each to Matplotlib's font cache.
for font_file in font_files:
fm.fontManager.addfont(font_file)
# Use your new font on all your plots.
plt.rc('font', family='Open Sans')
Note, a few times this didn't work properly and the requested font wasn't displayed (even though no error or warning was shown). If that happens, try factory resetting your Colab runtime and running again.
When matplotlib 3.2 is released, it will be easier.
# For now we must upgrade to 3.2 rc first
# !pip install -U --pre matplotlib
import matplotlib as mpl
mpl.font_manager.fontManager.addfont('thsarabunnew-webfont.ttf')
mpl.rc('font', family='TH Sarabun New')
I would like to add my solutions as another reference:
Change the seaborn style
I would strongly recommend this approach as changing the font family can be very troublesome and inconvenient per seaborn design (many of the posts are no longer working on my end in 2022/05). So if you just want to get rid of the stupid default font in matplotlib and seaborn and is OK with Arial, go and type
%matplotlib inline
import matplotlib.style as style
style.use('seaborn-deep')
Changing the font type (borrowed from top answers and tested myself. Restarting the runtime several times if it is not working as expected)
import matplotlib as mpl
import matplotlib.font_manager as fm
from matplotlib import font_manager as fm, pyplot as plt
!wget https://github.com/trishume/OpenTuringCompiler/blob/master/stdlib-sfml/fonts/Times%20New%20Roman.ttf
!wget https://github.com/matomo-org/travis-scripts/blob/master/fonts/Arial.ttf
font_files = fm.findSystemFonts()
# Go through and add each to Matplotlib's font cache.
for font_file in font_files:
fm.fontManager.addfont(font_file)
fm.fontManager.ttflist += fm.createFontList(['Times New Roman.ttf'])
# Use your new font on all your plots.
plt.rc('font', family='serif')
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2*np.pi*t)
plt.plot(t, s)
plt.xlabel('time (s)')
plt.ylabel('voltage (mV)')
plt.title('About as simple as it gets, folks')
plt.show()
Updates on 2022/06/08: Method 1 sometimes doesn't work out in Colab, but it works on the local Jupyter Notebook. It seems that explicitly installing and adding the font types is the only way if you want to customize font types on Colab.

Missing auto-complete for matplotlib in python 3 in pycharm (but for python 2.7 it works)

I have a strange problem:
from matplotlib import pyplot as plt
fig = plt.figure()
then, typing fig. there is no auto-complete popping up. Same for other modules like axes.
I am using pycharm. I am using python 3.6 on windows. For python 2.7 the auto-complete works.
This has annoyed me long enough. Apparently I am the only one using matplotlib in python 3 and pycharm who is too stupid to remember all methods of Figure and Axes.
But if I am not the only one, here is a workaround. Define your own function, write a proper docstring. For example:
def subplots(*args, **kwargs):
"""
Parameters
----------
args
kwargs
Returns
-------
f : matplotlib.figure.Figure
ax : matplotlib.axes.Axes
"""
f, ax = plt.subplots(*args, **kwargs)
return f, ax
pycharm understands what matplotlib.figure.Figure is, so here you go.

Custom fonts in Google Colaboratory matplotlib charts

Using custom fonts in matplotlib locally involves storing the .ttfs in the matplotlib/mpl-data/fonts/ttf/ folder, then calling mpl.font_manager._rebuild(), then setting mpl.rcParams['font.sans-serif'].
Is there any way to do this in Google Colaboratory, where it doesn't seem that this ttf folder is accessible?
For example, I'd like to use the Roboto font. After installing, this would be invoked using mpl.rcParams['font.sans-serif'] = 'Roboto'.
The ttf folder is here:
/usr/local/lib/python3.6/dist-packages/matplotlib/mpl-data/fonts/ttf
So you want to download the ttf there, e.g.:
!wget https://github.com/Phonbopit/sarabun-webfont/raw/master/fonts/thsarabunnew-webfont.ttf -P /usr/local/lib/python3.6/dist-packages/matplotlib/mpl-data/fonts/ttf
matplotlib.font_manager._rebuild()
matplotlib.rc('font', family='TH Sarabun New')
update 2019-12
_rebuild() no longer works. Here's another method which still works.
import matplotlib
import matplotlib.font_manager as fm
!wget https://github.com/Phonbopit/sarabun-webfont/raw/master/fonts/thsarabunnew-webfont.ttf
fm.fontManager.ttflist += fm.createFontList(['thsarabunnew-webfont.ttf'])
matplotlib.rc('font', family='TH Sarabun New')
Wanted to add a full, succinct answer that currently works.
# Download fonts of choice. Here we download Open Sans variants to
# the current directory.
# It's not necessary to download to the share or matplotlib folders:
# /usr/share/fonts/truetype
# /usr/local/lib/python3.6/dist-packages/matplotlib/mpl-data/fonts/ttf
!wget 'https://github.com/google/fonts/raw/master/apache/opensans/OpenSans-Regular.ttf'
!wget 'https://github.com/google/fonts/raw/master/apache/opensans/OpenSans-Light.ttf'
!wget 'https://github.com/google/fonts/raw/master/apache/opensans/OpenSans-SemiBold.ttf'
!wget 'https://github.com/google/fonts/raw/master/apache/opensans/OpenSans-Bold.ttf'
from matplotlib import font_manager as fm, pyplot as plt
# Pick up any fonts in the current directory.
# If you do end up downloading the fonts to /usr/share/fonts/truetype,
# change this to: fm.findSystemFonts()
font_files = fm.findSystemFonts('.')
# Go through and add each to Matplotlib's font cache.
for font_file in font_files:
fm.fontManager.addfont(font_file)
# Use your new font on all your plots.
plt.rc('font', family='Open Sans')
Note, a few times this didn't work properly and the requested font wasn't displayed (even though no error or warning was shown). If that happens, try factory resetting your Colab runtime and running again.
When matplotlib 3.2 is released, it will be easier.
# For now we must upgrade to 3.2 rc first
# !pip install -U --pre matplotlib
import matplotlib as mpl
mpl.font_manager.fontManager.addfont('thsarabunnew-webfont.ttf')
mpl.rc('font', family='TH Sarabun New')
I would like to add my solutions as another reference:
Change the seaborn style
I would strongly recommend this approach as changing the font family can be very troublesome and inconvenient per seaborn design (many of the posts are no longer working on my end in 2022/05). So if you just want to get rid of the stupid default font in matplotlib and seaborn and is OK with Arial, go and type
%matplotlib inline
import matplotlib.style as style
style.use('seaborn-deep')
Changing the font type (borrowed from top answers and tested myself. Restarting the runtime several times if it is not working as expected)
import matplotlib as mpl
import matplotlib.font_manager as fm
from matplotlib import font_manager as fm, pyplot as plt
!wget https://github.com/trishume/OpenTuringCompiler/blob/master/stdlib-sfml/fonts/Times%20New%20Roman.ttf
!wget https://github.com/matomo-org/travis-scripts/blob/master/fonts/Arial.ttf
font_files = fm.findSystemFonts()
# Go through and add each to Matplotlib's font cache.
for font_file in font_files:
fm.fontManager.addfont(font_file)
fm.fontManager.ttflist += fm.createFontList(['Times New Roman.ttf'])
# Use your new font on all your plots.
plt.rc('font', family='serif')
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2*np.pi*t)
plt.plot(t, s)
plt.xlabel('time (s)')
plt.ylabel('voltage (mV)')
plt.title('About as simple as it gets, folks')
plt.show()
Updates on 2022/06/08: Method 1 sometimes doesn't work out in Colab, but it works on the local Jupyter Notebook. It seems that explicitly installing and adding the font types is the only way if you want to customize font types on Colab.

MatPlotlib from Spyder vs IPython

I'm working through a tutorial on MatPlotlib and I initially started using Spyder's IPython console. The very simple code:
import matplotlib.pyplot as plt
x = range(1, 5)
plt.plot(x, [xi*1.5 for xi in x])
plt.plot(x, [xi*3.0 for xi in x])
plt.plot(x, [xi/3.0 for xi in x])
plt.show()
in Ipython only produces a plot once plt.show() is executed, and that plot has 3 lines on it - as expected. But in Spyder's IPython console, I get a plot every time plt.plot() is executed, and plt.show() doesn't seem to have any effect at all. Each individual plot only has one line plotted on it rather than the 3 lines I see at the end of the code with IPython.
Is there a way to make Spyder behave like IPython?

Graphing matplotlib with Python code in a R Markdown document

Is it possible to use Python matplotlib code to draw graph in RStudio?
e.g. below Python matplotlib code:
import numpy as np
import matplotlib.pyplot as plt
n = 256
X = np.linspace(-np.pi,np.pi,n,endpoint=True)
Y = np.sin(2*X)
plt.plot (X, Y+1, color='blue', alpha=1.00)
plt.plot (X, Y-1, color='blue', alpha=1.00)
plt.show()
Output graph will be:
Then I need to write a R Markdown to include these code and generate graph automatically after knitting the markdown.
install.packages('devtools') first, get install_github function
install_github("rstudio/reticulate") install the dev version of reticulate
in r markdown doc, use code below to enable the function.
```{r setup, include=FALSE}
library(knitr)
library(reticulate)
knitr::knit_engines$set(python = reticulate::eng_python)
```
Try it , you will get what you want and don't need to save any image.
One possible solution is save the plot as a image, then load the file to markdown.
### Call python code sample
```{r,engine='python'}
import numpy as np
import matplotlib.pyplot as plt
n = 256
X = np.linspace(-np.pi,np.pi,n,endpoint=True)
Y = np.sin(2*X)
fig, ax = plt.subplots( nrows=1, ncols=1 )
ax.plot (X, Y+1, color='blue', alpha=1.00)
ax.plot (X, Y-1, color='blue', alpha=1.00)
#plt.show()
fig.savefig('foo.png', bbox_inches='tight')
print "finished"
```
Output image:
![output](foo.png)
#### The End
Output:
You can do that with reticulate, but most time in trying to follow a tutorial in doing that you may encounter some technicalities that weren't sufficiently explained.
My answer is a little late but I hope it's a thorough walkthrough of doing it the right way - not rendering it and then loading it as a png but have the python code executed more "natively".
Step 1: Configure Python from RStudio
You want to insert an R chunk, and run the following code to configure the path to the version of Python you want to use. The default python that comes shipped with most OS is usually the outdated python 2 and is not where you install your packages. That is the reason why it's important to do this, to make sure Rstudio will use the specified python instance where your matplotlib library (and the other libraries you will be using for that project) can be found:
library(reticulate)
# change the following to point to the desired path on your system
use_python('/Users/Samuel/anaconda3/bin/python')
# prints the python configuration
py_config()
You should expect to see that your session is configured with the settings you specified:
python: /Users/Samuel/anaconda3/bin/python
libpython: /Users/Samuel/anaconda3/lib/libpython3.6m.dylib
pythonhome: /Users/Samuel/anaconda3:/Users/Samuel/anaconda3
version: 3.6.3 |Anaconda custom (64-bit)| (default, Oct 6 2017, 12:04:38) [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]
numpy: /Users/Samuel/anaconda3/lib/python3.6/site-packages/numpy
numpy_version: 1.15.2
python versions found:
/Users/Samuel/anaconda3/bin/python
/usr/bin/python
/usr/local/bin/python
/usr/local/bin/python3
/Users/Samuel/.virtualenvs/r-tensorflow/bin/python
Step 2: The familiar plt.show
Add a Python chunk (not R!) in your R Markdown document (see attached screenshot) and you can now write native Python code. This means that the familiar plt.show() and plt.imshow() will work without any extra work. It will be rendered and can be compiled into HTML / PDF using knitr.
This will work:
plt.imshow(my_image, cmap='gray')
Or a more elaborated example:
import numpy as np
import matplotlib.pyplot as plt
import os
import cv2
DATADIR = '/Users/Samuel/Datasets/PetImages'
CATEGORIES = ['Dog', 'Cat']
for category in CATEGORIES:
path = os.path.join(DATADIR, category) # path to cat or dog dir
for img in os.listdir(path):
img_array = cv2.imread(os.path.join(path,img), cv2.IMREAD_GRAYSCALE)
plt.imshow(img_array, cmap='gray')
plt.show()
break
break
Output:
Step 3: Knit to HTML / PDF / Word etc
Proceed to knit as usual. The end product is a beautifully formatted document done in Python code using R Markdown. RStudio has come a long way and I'm surprised the level of support it has for Python code isn't more known so hoping anyone that stumbled upon this answer will find it informative and learned something new.
I have been working with reticulate and R Markdown and you should specify your virtual environment. For example my R Markdown starts as follows:
{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, warning = FALSE, cache.lazy = FALSE)
library(reticulate)
use_condaenv('pytorch') ## yes, you can run pytorch and tensor flow too
Then you can work in either language. So, for plotting with matplotlib, I have found that you need the PyQt5 module to make it all run smoothly. The following makes a nice plot inside R Markdown - it's a separate chunk.
{python plot}
import PyQt5
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure
data = pd.read_csv('Subscriptions.csv',index_col='Date', parse_dates=True)
# make the nice plot
# set the figure size
fig = plt.figure(figsize = (15,10))
# the series
ax1 = fig.add_subplot(211)
ax1.plot(data.index.values, data.Opens, color = 'green', label = 'Opens')
# plot the legend for the first plot
ax1.legend(loc = 'upper right', fontsize = 14)
plt.ylabel('Opens', fontsize=16)
# Hide the top x axis
ax1.axes.get_xaxis().set_visible(False)
####### NOW PLOT THE OTHER SERIES ON A SINGLE PLOT
# plot 212 is the MI series
# plot series
ax2 = fig.add_subplot(212)
ax2.plot(data.index.values, data.Joiners, color = 'orange', label = 'Joiners')
# plot the legend for the second plot
ax2.legend(loc = 'upper right', fontsize = 14)
# set the fontsize for the bottom plot
plt.ylabel('Joiners', fontsize=16)
plt.tight_layout()
plt.show()
You get the following from this:
I don't have the reputation points to add a comment, but Bryan's answer above was the only one to work for me. Adding plt.tight_layout() made the difference. I added that line to the following simple code and the plot displayed.
{python evaluate}
plt.scatter(X_train, y_train, color = 'gray')
plt.plot(X_train, regresssion_model_sklearn.predict(X_train), color = 'red')
plt.ylabel('Salary')
plt.xlabel('Number of Years of Experience')
plt.title('Salary vs. Years of Experience')
plt.tight_layout()
plt.show()