Customize font when using style sheet - python

I am using the 'ggplot' style sheet. Now, the style is great, except that I would like to specifically change the font style. Is that possible?
If found the documentation about customizing styles. However, I just want to change the font while keeping the rest of the style.
Also, does anyone know where to see the setting-details of each style (like font, figsize, etc.)?
plt.imshow(ori, vmin = 0, vmax = 300)
plt.style.use('ggplot')
plt.show()

Combining styles
I think that the most elegant is to combine styles.
For example, you could define your own font settings in mystyle.mplstyle (see below where to save it, and what it could look like). To get the ggplot style with your own font settings you would then only have to specify:
plt.style.use(['ggplot', 'mystyle'])
This solution is elegant, because it allows consistent application in all your plots and allows you to mix-and-match.
Where to save your custom style?
Taken from one of my own styles mystyle.mplstyle could have the following entries (you should customise to your need obviously):
font.family : serif
font.serif : CMU Serif
font.weight : bold
font.size : 18
text.usetex : true
Which you should save it matplotlib's configuration directory. For me this is ~/.matplotlib/stylelib/, but use
import matplotlib
matplotlib.get_configdir()
to find out what to use on your operating system. See documentation. You could also write a Python function to install in the right location.
Where to find existing styles?
Then the final part of your question. First, it is usefull to know that you can obtain a list with available styles using
import matplotlib.pyplot as plt
plt.style.available
See the documentation for a graphical representation.
How to inspect for example ggplot.mplstyle? I think that the best reference in matplotlib's source. You can also find the *.mplstyle files on your system. Where, however, depends on your operating system and installation. For me
find / -iname 'ggplot.mplstyle' 2>/dev/null
gives
/usr/local/lib/python3.7/site-packages/matplotlib/mpl-data/stylelib/ggplot.mplstyle
Or more generally you could search for all styles:
find / -iname '*.mplstyle' 2>/dev/null
For Windows I am not really an expert, but maybe the file-paths that were listed above give you a clue where to look.
Python script to install style in the right location
To install your custom styles in the right location, you could build a script that looks something like:
def copy_style():
import os
import matplotlib
# style definition(s)
styles = {}
styles['mystyle.mplstyle'] = '''
font.family : serif
'''
# write style definitions
# directory name where the styles are stored
dirname = os.path.abspath(os.path.join(matplotlib.get_configdir(), 'stylelib'))
# make directory if it does not yet exist
if not os.path.isdir(dirname): os.makedirs(dirname)
# write all styles
for fname, style in styles.items():
open(os.path.join(dirname, fname),'w').write(style)

Yes, it is possible. And you can do it either locally by passing the font to individual labels
font = {'fontname':'your font'}
plt.xlabel('xlabel', **hfont)
plt.ylabel('xlabel', **hfont)
or globally
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'your font'

Try rcParams
matplotlib.rcParams.update({'font.size': 12})
Read more matplotlib

Related

How to save a Bokeh plot as PDF?

I'm working with Bokeh a lot and I'm looking for a way to create a PDF from the figure I created.
Is there an option to achieve this goal?
This is possible with a combination of the three python package bokeh, svglib and reportlab which works perfect for me.
This will include 3 steps:
creating a bokeh svg output
read in this svg
saving this svg as pdf
Minimal Example
To show how this could work please see the following example.
from bokeh.plotting import figure
from bokeh.io import export_svgs
import svglib.svglib as svglib
from reportlab.graphics import renderPDF
test_name = 'bokeh_to_pdf_test'
# Example plot p
p = figure(plot_width=400, plot_height=400, tools="")
p.circle(list(range(1,6)),[2, 5, 8, 2, 7], size=10)
# See comment 1
p.xaxis.axis_label_standoff = 12
p.xaxis.major_label_standoff = 12
# step 1: bokeh save as svg
p.output_backend = "svg"
export_svgs(p, filename = test_name + '.svg')
# see comment 2
svglib.register_font('helvetica', '/home/fonts/Helvetica.ttf')
# step 2: read in svg
svg = svglib.svg2rlg(test_name+".svg")
# step 3: save as pdf
renderPDF.drawToFile(svg, test_name+".pdf")
Comment 1
There is an extra information used for axis_label_standoff and major_label_standoff because the ticks of the x-axis are moving without this definition a bit up and this looks not so good.
Comment 2
If you get a long list of warnings like
Unable to find a suitable font for 'font-family:helvetica'
Unable to find a suitable font for 'font-family:helvetica'
....
Unable to find a suitable font for 'font-family:helvetica'
the ppdf is still created. This warning appears because the default font in bokeh is named helvetica, which is not known by svglib. svglib looks for this font at a defined place. If this font is not there, the message appears. This means bokeh will use its own default font instead.
To get rid of this message you can register a font in svglib like this
# name in svglib, path to font
svglib.register_font('helvetica' , f'/{PATH_TO_FONT}/Helvetica.ttf')
right before calling svglib.svg2rlg().
Output
This code will create the same figure twice, once with the suffix .svg and once with the suffix .pdf.
The figure looks like this:

xlwings: set cell formatting from python on a Mac specifically

I'm trying to format font size, font color, horizontal alignment, border style/weight etc on a worksheet using python xlwings on a Mac. I know you'd have to use the missing features to do this type of editing on python but i don't know what API member functions to use in order to do these formatting on Mac. The ones for windows I can find everywhere; for example:
import xlwings
wb = xlwings.Book('checker_output.xlsx')
wb.sheets.add('sheet1')
sht = wb.sheets['sheet1']
sht.range('A3:A26').api.Font.Size = 15
would work on the windows API, but not on a mac. Any work around for this?
I found you can use .api to center / left / right align but this is on a PC, perhaps it can work on Mac as well.
Set the value of the HorizontalAlignment property of the cell to:
Center-aligned, we’d set HorizontalValue to -4108;
Right-aligned, we’d set HorizontalValue to -4152;
Left-aligned, we’d set HorizontalValue to -4131;
What it would look like:
import xlwings as xw
sht = xw.sheets.active
sht.range(f'$A1:$C5').api.HorizontalAlignment = -4131

How to make my matplotlib rc module preferable parameters as defaults to all my python files?

I have the following code at my python scripts
from matplotlib import rc
rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
rc('text', usetex=True)
params = {'text.usetex': True,
'axes.labelsize': 18}`
I want to have those preference as defaults when I start a python console instead of copy paste all the time.
Do you know if this is possible?
Cheers!
Customize your matplotlibrc file by adding or uncommenting:
font.family : sans-serif
font.sans-serif : Helvetica
text.usetex : True
axes.labelsize : 18
See ThePredator's answer to find out where your matplotlibrc file is located.
You can see the webpage for more details
Use mpl.matplotlib_fname() to get your rc file path, and modify it according to your manual settings.
In [1]: import matplotlib as mpl
In [2]: mpl.matplotlib_fname()
Out[2]: '/etc/matplotlibrc'
In my case the file exists at /etc/matplotlibrc

Convert SVG/PDF to EMF

I am looking for a way to save a matplotlib figure as an EMF file. Matplotlib allows me to save as either a PDF or SVG vector file but not as EMF.
After a long search I still cannot seem to find a way to do this with python. Hopefully anyone has an idea.
My workaround is to call inkscape using subprocess but this is far from ideal as I would like to avoid the use of external programs.
I'm running python 2.7.5 and matplotlib 1.3.0 using the wx backend.
For anyone who still needs this, I wrote a basic function that can let you save a file as an emf from matplotlib, as long as you have inkscape installed.
I know the op didn't want inkscape, but people who find this post later just want to make it work.
import matplotlib.pyplot as plt
import subprocess
import os
inkscapePath = r"path\to\inkscape.exe"
savePath= r"path\to\images\folder"
def exportEmf(savePath, plotName, fig=None, keepSVG=False):
"""Save a figure as an emf file
Parameters
----------
savePath : str, the path to the directory you want the image saved in
plotName : str, the name of the image
fig : matplotlib figure, (optional, default uses gca)
keepSVG : bool, whether to keep the interim svg file
"""
figFolder = savePath + r"\{}.{}"
svgFile = figFolder.format(plotName,"svg")
emfFile = figFolder.format(plotName,"emf")
if fig:
use=fig
else:
use=plt
use.savefig(svgFile)
subprocess.run([inkscapePath, svgFile, '-M', emfFile])
if not keepSVG:
os.system('del "{}"'.format(svgFile))
#Example Usage
import numpy as np
tt = np.linspace(0, 2*3.14159)
plt.plot(tt, np.sin(tt))
exportEmf(r"C:\Users\userName", 'FileName')
I think the function is cool but inkscape syntax seems not working in my case. I search in other post and find it as:
inkscape filename.svg --export-filename filename.emf
So if I replace -M by --export-filename within the subprocess argument, everything works fine.

Writing Greek in matplotlib labels, titles

I am trying to write some text in Greek for labels, figure title etc. to accompany my plots but so far to no avail.
I don't want to print specific letters (I know how to do this using the special characters notation), I'd rather write the whole text in Greek (probably using Unicode and u'text' ?).
Before receiving suggestions I would like to mention that for some reason I can't get matplotlib to cooperate with TeX (using Ipython notebook from anaconda in Ubuntu 14.10), so that wouldn't really be an option.
I tried loading Arial font and it does load successfully but again I get square blocks instead of characters. I used
import matplotlib.font_manager as fm
prop = fm.FontProperties(fname='/usr/share/fonts/truetype/msttcorefonts/Arial.ttf')
and then for displaying the string I used u'Αποτελέσματα προσομοίωσης'. Arial is supposed to render Greek perfectly and I have used it many times in text editors.
I managed to solve the problem by doing the following:
First, you have to import the necessary libraries and set a font installed on the computer that can for sure render Greek, like the Ubuntu font (Ubuntu Bold in the following code).
import matplotlib.font_manager as fm
fp1 = fm.FontProperties(fname='/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf')
then you can specifically apply the chosen font to each label, title etc as follows:
plt.title(u"Τίτλος του γραφήματος",fontproperties=fp1)
If that doesn't seem to work, try adding the following line at the beginning of the file:
# -*- coding: utf-8 -*-
A sample plot is provided to prove the correctness of the code:
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import numpy as np
fp1 = fm.FontProperties(fname='/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf')
data = np.random.randn(5000) #generate some random data
plt.plot(data)
plt.title(u"Τίτλος του γραφήματος", fontproperties=fp1)
plt.xlabel(u"Άξονας x", fontproperties=fp1)
plt.ylabel(u"Άξονας y", fontproperties=fp1)
plt.show()
It should give you something like that:

Categories