ProPlot basic syntax and features

Introduction

The drawing conditions of multi-layer elements (fonts, coordinate axes, legends, etc.) in scientific research papers have put forward higher requirements. We need to change multiple drawing parameters in Matplotlib and Seaborn, especially when drawing complex graphics with multiple subgraphs. When doing this, it is easy to cause the drawing code to be lengthy.

As a concise Matplotlib wrapper, the ProPlot library is a high-level encapsulation of Matplotlib's object-oriented interface. It integrates the cartopy/Basemap map library , xarray and pandas , which can make up for some of the shortcomings of Matplotlib. ProPlot allows Matplotlib enthusiasts to have a smoother drawing experience.

Multiple subgraph drawing processing

Shared axis labels

When using Matplotlib to draw multiple subplots, it is inevitable to perform repeated drawing operations of axis scale labels, axis labels, colorbars and legends, resulting in lengthy drawing code. In addition, we also need to add sequential labels (such as a, b, c, etc.) to each subgraph. ProPlot can draw different styles of subplot labels directly through its built-in methods, while Matplotlib needs to draw through custom functions.

The , , parameters figure ()of the function in ProPlot can be used to control different axis label styles. Their optional values ​​and descriptions are as follows:sharexshareyshare

The following is a schematic diagram of multi-subfigure axis label sharing drawn using ProPlot, in which

  • (a) is a shared axis label style;
  • (b) Set the Y-axis shared label style;
  • (c) shows the style when the Y-axis sharing mode is set to Limits. It can be seen that the scale range of each subgraph is forced to be the same, resulting in some subgraphs being incompletely displayed;
  • (d) shows the style when the Y-axis sharing mode is set to True. At this time, the axis labels and scale labels are shared.
import pandas as pd
import numpy as np
import proplot as pplt
import matplotlib.pyplot as plt

N = 50
M = 40
state = np.random.RandomState(51423)
cycle = pplt.Cycle('grays', M, left=0.1, right=0.8)

datas = []
for scale in (1, 3, 7, 0.2):
    data = scale * (state.rand(N, M) - 0.5).cumsum(axis=0)[N // 2:, :]
    datas.append(data)

# Plots with different sharing and spanning settings
# Note that span=True and share=True are the defaults
spans = (False, False, False, False)
shares = (False, 'labels', 'limits', True)
for i, (span, share) in enumerate(zip(spans, shares)):
	# note: there is sharey
    fig = pplt.figure(refaspect=1, refwidth=1.06, spanx=span, sharey=share)
    axs = fig.subplots(ncols=3)
    for ax, data in zip(axs, datas):
        on = ('off', 'on')[int(span)]
        ax.plot(data, cycle=cycle)
        ax.format(
            grid=False, xlabel='X labels', ylabel='shared axis',
            #suptitle=f'Sharing mode {share!r} (level {i}) with spanning labels {on}'
        )
        fig.save(r'\第2章 绘制工具及其重要特征\Proplot_subplot_share'+str(share)+'.png', bbox_inches='tight',dpi=600)
        fig.save(r'\第2章 绘制工具及其重要特征\\Proplot_subplot_share'+str(share)+'.pdf', bbox_inches='tight')

plt.show()

"Span" axis label

figure()spanxThe, spanyand parameters in the function spanare used to control whether to use the "span" axis label for the X-axis, Y-axis, or both axes. That is, when the X-axis and Y-axis labels of multiple subgraphs are the same, just use one axis label instead.

import pandas as pd
import numpy as np
import proplot as pplt
import matplotlib.pyplot as plt


state = np.random.RandomState(51423)

# Plots with minimum and maximum sharing settings
# Note that all x and y axis limits and ticks are identical
spans = (True, True)
shares = (True, 'all')
titles = ('Minimum sharing', 'Maximum sharing')
for span, share, title in zip(spans, shares, titles):
    fig = pplt.figure(refwidth=1, span=span, share=share)
    axs = fig.subplots(nrows=2, ncols=4)
    for ax in axs:
        data = (state.rand(100, 20) - 0.4).cumsum(axis=0)
        ax.plot(data, cycle='grays')
    axs.format(
        xlabel='xlabel', ylabel='ylabel',
        grid=False, xticks=25, yticks=5,labelsize=13
    )
fig.save(r'\第2章 绘制工具及其重要特征\图2-3-2 Proplot_subplot_span.png', 
         bbox_inches='tight',dpi=600)
fig.save(r'\第2章 绘制工具及其重要特征\图2-3-2 Proplot_subplot_span.pdf', 
         bbox_inches='tight')
         
         
plt.show()

Drawing of multiple sub-picture serial numbers

When there are multiple subfigures in a scientific research paper, one task is to label each subfigure with a serial number . The ProPlot library provides flexible format ()methods for drawing objects (figure.Figure and axes.Axes) that can be used to draw different subfigure number styles and positions.

format() The optional values ​​​​of the positional parameter (abcloc) in the function are as follows:


Among them, sub-picture numbers G ~ I have a background border added, which is achieved by setting format ()the parameter of the function to True. abcbboxIn addition, the parameters abcborder, abc_kwand abctitlepadare used to control the text border, text properties (color, thickness, etc.) of the sub-picture serial number, sub-picture serial number and sub-picture title spacing properties respectively.

import pandas as pd
import numpy as np
import proplot as pplt
import matplotlib.pyplot as plt


fig = pplt.figure(figsize=(8,5.5),space=1, refwidth='10em')
axs = fig.subplots(nrows=3, ncols=3)
locs = ("c","l","r","lc","uc","ur","ul","ll","lr")
abcs = ("a","a.","(a)","[a]","(a","A","A.","(A)","(A.)")
axs.format(abcsize=16,xlabel='x axis', ylabel='y axis',labelsize=18) 
axs[-3:].format(abcbbox=True) 
axs[0, 0].format(abc="a", abcloc="c",abcborder=True)  
axs[0, 1].format(abc="a.", abcloc="l")  
axs[0, 2].format(abc="(a)", abcloc="r")  
axs[1, 0].format(abc="[a]", abcloc="lc",facecolor='gray5')  
axs[1, 1].format(abc="(a", abcloc="uc",facecolor='gray5')  
axs[1, 2].format(abc="A", abcloc="ur",facecolor='gray5')  
axs[2, 0].format(abc="A.", abcloc="ul",)  
axs[2, 1].format(abc="(A)", abcloc="ll")  
axs[2, 2].format(abc="(A.)", abcloc="lr") 
fig.save(r'\第2章 绘制工具及其重要特征\\图2-3-3 Proplot_abc.png', 
         bbox_inches='tight',dpi=600)
fig.save(r'\第2章 绘制工具及其重要特征\\图2-3-3 Proplot_abc.pdf', 
         bbox_inches='tight')
plt.show()

For more examples of adding and modifying subplot properties, see the ProPlot official tutorial.

Simpler colorbar and legend

In the process of using Matplotlib, it is sometimes troublesome to draw the legend outside the subplot. Usually, we need to manually position the legend and adjust the spacing between the graph and the legend to make room for the legend in the drawing object. In addition, when drawing a colorbar outside a subfigure, for example , some space needs to be borrowed from the parent figure, which may cause asymmetry infig.colorbar (..., ax=ax) the display of graphic objects with multiple subfigures . In Matplotlib, it is often difficult to draw color bars inserted inside the drawing object and generate color bars outside the subplot with the same width, because the inserted color bar will be too wide or too narrow, and there will be problems such as inconsistency with the entire subplot . .

The colorbar is a small strip-shaped image next to the main image, which can assist in representing the color composition of the colormap in the main image and the corresponding relationship between colors and values .

There is a simple framework in the ProPlot library specifically for drawing color bars and legends of a single subfigure or multiple consecutive subfigures . This framework passes the position parameters to ProPlot's axes.Axes.colorbaror axes.Axes.legendto complete the drawing of color bars or legends at different positions of a specific subfigure. .

import pandas as pd
import numpy as np
import proplot as pplt
import matplotlib.pyplot as plt

fig = pplt.figure(share=False, refwidth=2.3)

# Colorbars
ax = fig.subplot(121)
state = np.random.RandomState(51423)
m = ax.heatmap(state.rand(10, 10), colorbar='t', cmap='grays')
ax.colorbar(m, loc='r')
ax.colorbar(m, loc='ll', label='colorbar label')
ax.format(title='Axes colorbars')

# Legends
ax = fig.subplot(122)
ax.format(title='Axes legends', titlepad='0em')
hs = ax.plot(
    (state.rand(10, 5) - 0.5).cumsum(axis=0), linewidth=3,
    cycle='ggplot', legend='t',
    labels=list('abcde'), legend_kw={
    
    'ncols': 5, 'frame': False}
)
ax.legend(hs, loc='r', ncols=1, frame=False)
ax.legend(hs, loc='ll', label='legend label')
fig.format(abc="(a)", abcloc="ul",abcsize=15, 
           xlabel='xlabel', ylabel='ylabel')
           
fig.save('\第2章 绘制工具及其重要特征\图2-3-4 Proplot_axes_cb_legend.png', 
         bbox_inches='tight',dpi=600)
fig.save('\第2章 绘制工具及其重要特征\图2-3-4 Proplot_axes_cb_legend.pdf', 
         bbox_inches='tight')
plt.show()

To draw a color bar or legend along the edge of the graph, use proplot.figure.Figure.colorbarand proplot.figure.Figure.legend.

import pandas as pd
import numpy as np
import proplot as pplt
import matplotlib.pyplot as plt


state = np.random.RandomState(51423)
fig, axs = pplt.subplots(
    ncols=2, nrows=2, order='F', refwidth=1.7, wspace=2.5, share=False
)

# Plot data
data = (state.rand(50, 50) - 0.1).cumsum(axis=0)
for ax in axs[:2]:
    m = ax.contourf(data, cmap='grays', extend='both')
hs = []
colors = pplt.get_colors('grays', 5)
for abc, color in zip('ABCDEF', colors):
    data = state.rand(10)
    for ax in axs[2:]:
        h, = ax.plot(data, color=color, lw=3, label=f'line {
      
      abc}')
    hs.append(h)

# Add colorbars and legends
fig.colorbar(m, length=0.8, label='colorbar label', loc='b', col=1, locator=5)
fig.colorbar(m, label='colorbar label', loc='l')
fig.legend(hs, ncols=2, center=True, frame=False, loc='b', col=2)
fig.legend(hs, ncols=1, label='legend label', frame=False, loc='r')
fig.format(abc='A', abcloc='ul')
for ax, title in zip(axs, ('2D {} #1', '2D {} #2', 'Line {} #1', 'Line {} #2')):
    ax.format(xlabel='xlabel', title=title.format('dataset'))
    
fig.save(r'\第2章 绘制工具及其重要特征\Proplot_figure_cb_legend.png', 
         bbox_inches='tight',dpi=600)
fig.save(r'\第2章 绘制工具及其重要特征\Proplot_figure_cb_legend.pdf', 
         bbox_inches='tight')
plt.show()

More beautiful colors and fonts

A common problem in scientific visualization is the use of misleading colormaps like "jet" to map corresponding values. This colormap has obvious visual flaws in hue, saturation and brightness. There are few color mapping options to choose from in Matplotlib. There are only a few color mappings with similar hues, which cannot handle more complex numerical mapping scenarios.

The ProPlot library encapsulates a large number of color mapping options. It not only provides expansion packages from Seaborn, cmOcean, SciVisColor, etc. and multiple color mapping options from projects such as Scientific color maps, but also defines some default color options and one for generating new ones. PerceptualColormap class for color bars.

Matplotlib's default plotting font is DejaVu Sans. This font is open source, but, from an aesthetic point of view, it is not very pleasing. The ProPlot library also comes with several other sans serif fonts and the entire TeX Gyre font family. These fonts are more in line with the drawing requirements of some scientific journals for the illustrations of scientific research papers.

Below are the renderings of different color mappings using ProPlot's different color mapping options.
(a) is the grays color map
(b) is the default viridis color map of Matplotlib
(c) is the mako color map in Seaborn
(d) is the marine color map in ProPlot
(e) is the dense color in cmOcean Mapping
(f) is the batlow color map in Scientific color maps.

import pandas as pd
import numpy as np
import proplot as pplt
import matplotlib.pyplot as plt


fig = pplt.figure(share=False, refwidth=2.3)

# Colorbars
ax = fig.subplot(231)
state = np.random.RandomState(51423)
data = 1 + (state.rand(12, 10) - 0.45).cumsum(axis=0)
m = ax.heatmap(state.rand(10, 10), cmap='grays')
ax.colorbar(m, loc='ll', label='grays colorbar')
ax = fig.subplot(232)
m = ax.heatmap(state.rand(10, 10), cmap='viridis')
ax.colorbar(m, loc='ll', label='viridis colorbar')

ax = fig.subplot(233)
m = ax.heatmap(state.rand(10, 10), cmap='mako')
ax.colorbar(m, loc='ll', label='mako colorbar')

ax = fig.subplot(234)
m = ax.heatmap(state.rand(10, 10), cmap='marine')
ax.colorbar(m, loc='ll', label='marine colorbar')

ax = fig.subplot(235)
m = ax.heatmap(state.rand(10, 10), cmap='dense')
ax.colorbar(m, loc='ll', label='dense colorbar')

ax = fig.subplot(236)
m = ax.heatmap(state.rand(10, 10), cmap='batlow')
ax.colorbar(m, loc='ll', label='batlow colorbar')

fig.format(abc="(a)", abcloc="ul",abcsize=15,
           xlabel='xlabel', ylabel='ylabel',labelsize=15)
           
fig.save(r'\第2章 绘制工具及其重要特征\图2-3-6 Proplot_colormaps.png', 
         bbox_inches='tight',dpi=600)
fig.save(r'\第2章 绘制工具及其重要特征\图2-3-6 Proplot_colormaps.pdf', 
         bbox_inches='tight')
plt.show()

For more color mapping drawings, please refer to the official ProPlot tutorial.

The following are the visual results of some font drawings in ProPlot. The three fonts shown in (a) (b) (c) are commonly used fonts in the drawing of scientific research papers.

import pandas as pd
import numpy as np
import proplot as pplt
import matplotlib.pyplot as plt
from proplot import rc

# Sample data
state = np.random.RandomState(51423)
data = state.rand(6, 6)
data = pd.DataFrame(data, index=pd.Index(['a', 'b', 'c', 'd', 'e', 'f']))

fig = pplt.figure(share=False, refwidth=2.3)
# 参数 rc 则用于覆盖预设样式字典中的值的参数映射,只更新样式中的一部分参数。
rc["font.family"] = "Times New Roman"
ax = fig.subplot(231)
m = ax.heatmap(
    data, cmap='grays',
    labels=True, precision=2, labels_kw={
    
    'weight': 'bold'}
)
ax.format(title='Times New Roman Font')

rc["font.family"] = "TeX Gyre Schola"
ax = fig.subplot(232)
m = ax.heatmap(
    data, cmap='grays',
    labels=True, precision=2, labels_kw={
    
    'weight': 'bold'}
)
ax.format(title='TeX Gyre Schola Font')

rc["font.family"] = "TeX Gyre Heros"
ax = fig.subplot(233)
m = ax.heatmap(
    data, cmap='grays',
    labels=True, precision=2, labels_kw={
    
    'weight': 'bold'}
)
ax.format(title='TeX Gyre Heros Font')

rc["font.family"] = "TeX Gyre Cursor"
ax = fig.subplot(234)
m = ax.heatmap(
    data, cmap='grays',
    labels=True, precision=2, labels_kw={
    
    'weight': 'bold'}
)
ax.format(title='TeX Gyre Cursor Font')

rc["font.family"] = "TeX Gyre Chorus"
ax = fig.subplot(235)
m = ax.heatmap(
    data, cmap='grays',
    labels=True, precision=2, labels_kw={
    
    'weight': 'bold'}
)
ax.format(title='TeX Gyre Chorus Font')

rc["font.family"] = "TeX Gyre Adventor"
ax = fig.subplot(236)
m = ax.heatmap(
    data, cmap='grays',
    labels=True, precision=2, labels_kw={
    
    'weight': 'bold'}
)
ax.format(title='TeX Gyre Adventor Font')

fig.format(abc="(a)", abcloc="ul",abcsize=15,
           xlabel='xlabel', ylabel='ylabel',labelsize=14)
           
           
fig.save(r'\第2章 绘制工具及其重要特征\图2-3-7 Proplot_fonts.png', 
         bbox_inches='tight',dpi=600)
fig.save(r'\第2章 绘制工具及其重要特征\图2-3-7 Proplot_fonts.pdf', 
         bbox_inches='tight')
plt.show()

The ProPlot drawing tool library is a third-party high-quality extension library based on the Python basic drawing tool Matplotlib. You can use its own drawing functions to draw different types of graphs, or you can only use its high-quality drawing themes, that is, import the ProPlot library.

The above code is based on ProPlot version 0.9.5 and does not include the upgrade and optimization parts of subsequent versions of Matplotlib 3.4.3. ProPlot version 0.9.5 does not support Matplotlib 3.5 series versions. If you want to use ProPlot to draw graphical results with different needs or use ProPlot's high-quality academic style drawing theme, you can install the Matplotlib 3.4 series version yourself.

Reference books: Ning Haitao. Guide to illustrating scientific research papers - based on Python[M]. Beijing: People's Posts and Telecommunications Press, 2023: 36-42.

Guess you like

Origin blog.csdn.net/m0_52316372/article/details/132490330