姿态 -- a site by bzy

1011 – Matplotlib in Julia

research |

programming | Julia | plotting | Matplotlib |

Matplotlib has long been my favorite plotting engine behind Python for many years. See a beautiful galary here. After I turned to Julia several months ago, I have been a big fan of the fine lady for its elegance and power, especially how fast and efficiently she processes her jobs (well, let’s face it: Python is SLOW). I didn’t realize it until a few days ago that Matplotlib is fully functional in Julia as well, with some syntax change, and most likely that is the only difference. Hence this blog, in which I plan to share some of my favorite tricks in making beautiful graphs in Matplotlib under Julia. (Again, if you compare, Julia renders Matplotlib graphs much faster than Python does.)

To begin with, PyPlot must be installed in Julia. Simply run

1
Pkg.add(“PyPlot”)

in Julia will do the trick. Refer to the installation guide here for more details.

Then, we are ready to go.

1. Arrowed spines

I am old fashioned on this aspect. Whenever I draw a graph, I insist to have the arrows on the axes, just like what my middle school math teacher insisted. Here is how to do that in Matplotlib in Julia. First, you need the following auxiliary function to “draw an arrow”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
## arrowed_spines for plots: https://gist.github.com/joferkington/3845684
function arrowed_spines(ax; arrow_length=20, labels=(“”, “”), arrowprops=[])
    xlabel, ylabel = labels
    if isempty(arrowprops)
        arrowprops = {:arrowstyle=>“<|-”, :facecolor=>“black”}
    end
    t = 0; xy = 0; xycoords = 0; xytext = “”; textcoords = 0; ha = 0; va = 0
    for (i,spine) in enumerate([“left”, “bottom”])
        # Set up the annotation parameters
        t = ax[:spines][spine]:get_transform
        xy, xycoords = [.98, 0], (“axes fraction”, t)
        xytext, textcoords = [arrow_length, 0], (“offset points”, t)
        ha, va = “left”, “bottom”
        if spine == “bottom”
            xarrow = ax[:annotate](xlabel, xy, xycoords=xycoords, xytext=xytext,
                textcoords=textcoords, ha=ha, va=“center”, arrowprops=arrowprops)
        else
            yarrow = ax[:annotate](ylabel, xy[end:-1:1], xycoords=xycoords[end:-1:1],
                xytext=xytext[end:-1:1], textcoords=textcoords[end:-1:1],
                ha=“center”, va=va, arrowprops=arrowprops)
        end
    end
end

Note I have adopted this technique from joferkington and rewritten it into Her Elegance’s tongue (i.e. in Julia).

Once this auxiliary function has been defined, you can use it after creating a plot.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
### Example 1

## matplotlib settings: allow for LaTeX PyPlot.matplotlib[:rc](“text”, usetex=true) # allow tex rendering

## compute x = 0.0:0.1:5.0 y = exp(sin(x))

## set up canvas fig = PyPlot.figure(figsize=(6,4.5), facecolor=“w”, dpi=120) # create figure fig[:subplots_adjust](left=.1, right=.9, bottom=0.1, top=.9) # reduce white spaces ax = fig[:add_subplot](111) # create axis

## plot ax[:plot](x,y,ls=“-”,lw=1.2,c=“b”) # ls: linestyle, lw: lineweight, c: color, b: blue

## format axis ax[:spines][“right”][:set_visible](false) ax[:spines][“top”][:set_visible](false) ax[:yaxis][:set_ticks_position](“left”) # only show vertical ticks on left ax[:xaxis][:set_ticks_position](“bottom”) # only show horizontal ticks on bottom arrowed_spines(ax,arrow_length=15) # add arrows to spines ax[:annotate](L"\shortstack[l]{y-axis label, $y$}“,xy=(0.03,1.0),xycoords="axes fraction”) # y label ax[:annotate](L"\shortstack[r]{x-axis\label, $\chi$}“,xy=(0.87,0.04),xycoords="axes fraction”) # x label

## set limits ax:set_ylim

And the result should look like the following: Example 1 (Note that you should have a running LaTeX engine behind all these. Otherwise Matplotlib would not be able to parse LaTeX codes.)

2. Fonts: Serif v.s. Sans-serif

Over the years, I learned that fonts matter a lot. For example, in a presentation, sans-serif fonts are preferred when prejected through an overhead. In print, however, serif fonts are preferred. How to adjust fonts, and which fonts, in Matlplotlib?

I have a preference for newtxsf and newtxmath. (This is just a suggestoin and you can actually choose whatever fonts you want, provided they are supported in your LaTeX system.)

Below is the script I have at the beginning of my Julia script, before running any plotting functions.

1
2
3
4
5
6
7
8
9
10
11
12
13
fonttype = “serif”
# fonttype = “sansserif”

PyPlot.matplotlib[:rc](“text”, usetex=true) # allow tex rendering PyPlot.matplotlib[:rcParams][“text.latex.unicode”] = true if fonttype==“serif” # use serif math font PyPlot.matplotlib[:rc](“font”, family=“serif”, serif=“Times”, size=16) PyPlot.matplotlib[:rc](“text.latex”,preamble=\usepackage{newtxmath}”) else # use sans serif math font PyPlot.matplotlib[:rc](“font”, family=“sans-serif”, size=16) PyPlot.matplotlib[:rc](“text.latex”,preamble=\usepackage{newtxsf}”) end PyPlot.matplotlib[:rcParams][“text.latex.unicode”] = false

On lines 1 and 2, I can switch whether I want all graphs later to be generated in (sans-)serif. For example, with the beautiful newtx fonts, the figure in example 1 now looks like: Example 2 serif And instead, with sans-serif font: Example 2 sans-serif

14:33:07, Jun 08, 2015
bzy@Fontainebleau