acgc.figstyle

Style settings for matplotlib, for publication-ready figures

Activate the style by importing this module:

from acgc import figstyle

Figures generated by Matplotlib will then use the new style. Additional colormaps and fonts will be loaded. The style includes grid lines (horizontal and vertical) by default. Turn these off and on with grid_off and grid_on:

figstyle.grid_off()

figstyle.grid_on()

The additional colormaps are from Fabio Crameri's Scientific color maps (https://github.com/callumrollo/cmcrameri).

  1#!/usr/bin/env python3
  2'''Style settings for matplotlib, for publication-ready figures
  3
  4Activate the style by importing this module:
  5
  6`from acgc import figstyle`
  7
  8Figures generated by Matplotlib will then use the new style. 
  9Additional colormaps and fonts will be loaded.
 10The style includes grid lines (horizontal and vertical) by default.
 11Turn these off and on with `grid_off` and `grid_on`:
 12
 13`figstyle.grid_off()`
 14
 15`figstyle.grid_on()`
 16
 17The additional colormaps are from Fabio Crameri's Scientific color maps 
 18(https://github.com/callumrollo/cmcrameri).
 19'''
 20
 21import os
 22import warnings
 23import matplotlib as mpl
 24import matplotlib.style as mstyle
 25import matplotlib.font_manager as mfonts
 26if 'inline' in mpl.get_backend():
 27    import matplotlib_inline
 28
 29# Path to this module
 30_PATH = os.path.dirname(__file__)
 31
 32def activate_style(grid=True,gridaxis='both',mathfont='regular'):
 33    '''Activate style sheet 
 34    
 35    Parameters
 36    ----------
 37    grid : bool, default=True
 38        turn grid lines on (True) or off (False)
 39    gridaxis : str, default='both'
 40        specifies which axes should have grid lines
 41    mathfont : str, default='regular'
 42        sets font used in mathtext, 'regular' uses same font as regular text.
 43        see `set_mathfont` for all options
 44    '''
 45    # Load settings from style file
 46    mstyle.use(os.path.join(_PATH,'acgc.mplstyle'))
 47
 48    # Set mathtext font
 49    set_mathfont(mathfont)
 50
 51    # Turn grid on or off
 52    if grid:
 53        grid_on(axis=gridaxis)
 54
 55    # Use high quality for inline images; Only use this if the inline backend is active
 56    # 'png' is default, 'svg' is also good
 57    if 'inline' in mpl.get_backend():
 58        matplotlib_inline.backend_inline.set_matplotlib_formats('retina')
 59
 60def deactivate_style():
 61    '''Restore rcParams prior to importing figstyle'''
 62    mpl.rcParams = _rcParams_old
 63
 64def set_mathfont(fontname=None):
 65    '''Set the font used for typsetting math in Matplotlib
 66
 67    Parameters
 68    ----------
 69    fontname : str, default=None
 70        Should be one of
 71        - None         : Restore mathtext font to settings before importing figstyle
 72        - 'regular'    : Use same font as regular text in math expressions (default).
 73                       Same as using \\mathregular or \\mathdefault in math expressions.
 74                       Best for mixing regular and math text for superscripts and subscripts.
 75                       May lack or have poor positioning of some math symbols (e.g. integrals).
 76                       This will overwrite mathtext.bf, mathtext.bfit, mathtext.it, 
 77                       mathtext.rm in rcParams.
 78        - 'custom'     : Uses custom settings from rcParams (mathtext.bf, .bfit, .it, .rm)
 79        - 'cm'         : Computer Modern (i.e. LaTeX default)
 80        - 'stix'       : STIX serif
 81        - 'stixsans'   : STIX sans-serif; best for sans-serif math
 82        - 'dejavuserif': DejaVu Serif (not recommended)
 83        - 'dejavusans' : DejaVu Sans (not recommended)
 84    '''
 85
 86    # Check that input has an allowed value
 87    allowedvalues = ['None','regular','custom','cm','stix','stixsans','dejavusans','dejavuserif']
 88    if (fontname not in allowedvalues) and (fontname is not None):
 89        raise ValueError('Font name should be one of the allowed values: '+','.join(allowedvalues))
 90
 91    if fontname is None:
 92        # Restore old mathtext settings
 93        mpl.rcParams.update( {key:_rcParams_old[key] for key in
 94                              ['mathtext.fontset','mathtext.bf','mathtext.bfit',
 95                               'mathtext.it','mathtext.rm']})
 96
 97    elif fontname == 'regular':
 98        # Set the math font to the font used for regular text
 99
100        # Name of the text font
101        textfont = mpl.rcParams[f'font.{mpl.rcParams["font.family"][0]:s}'][0]
102        # Use the same font for math
103        mpl.rcParams.update({'mathtext.fontset': 'custom',
104                            'mathtext.bf'   : f'{textfont}:bold',
105                            'mathtext.bfit' : f'{textfont}:italic:bold',
106                            'mathtext.it'   : f'{textfont}:italic',
107                            'mathtext.rm'   : f'{textfont}'})
108    else:
109        # Set the math font to the value provided
110        mpl.rcParams['mathtext.fontset'] = fontname
111
112def grid_off():
113    '''Turn off grid lines'''
114    mpl.rcParams['axes.grid'] = False
115
116def grid_on(axis='both'):
117    '''Turn on grid lines
118    
119    Parameters
120    ----------
121    axis : {'both', 'x', 'y'}
122        specifies which axes should have grid lines 
123    '''
124    mpl.rcParams['axes.grid'] = True
125    mpl.rcParams['axes.grid.axis'] = axis
126
127def load_fonts():
128    '''Load fonts contained in the acgc/fonts subdirectory'''
129
130    # User fonts
131    fonts_pylib = mfonts.findSystemFonts(os.path.join(_PATH,'fonts'))
132
133    # Cached fonts
134    fonts_cached = mfonts.fontManager.ttflist
135    fonts_cached_paths = [ font.fname for font in fonts_cached ]
136
137    # Add fonts that aren't already installed
138    rebuild = False
139    for font in fonts_pylib:
140        if font not in fonts_cached_paths:
141            if rebuild is False:
142                # Issue warning, first time only
143                warnings.warn('Rebuilding font cache. This can take time.')
144            rebuild = True
145            mfonts.fontManager.addfont(font)
146
147    # Save font cache
148    if rebuild:
149        cache = os.path.join(
150                        mpl.get_cachedir(),
151                        f'fontlist-v{mfonts.FontManager.__version__}.json'
152                    )
153        mfonts.json_dump(mfonts.fontManager, cache)
154
155def load_crameri_colormaps(noprefix=True):
156    '''Load Fabio Crameri's Scientific color maps
157
158    https://www.fabiocrameri.ch/colourmaps/
159    https://github.com/callumrollo/cmcrameri
160    
161    Parameters
162    ----------
163    noprefix : bool, default=True
164        If True, remove the 'cmc.' prefix from the colormap names
165    '''
166
167    # Import the colormaps; The registered names will be prefixed with 'cmc.'
168    try:
169        from cmcrameri import cm
170    except ImportError:
171        warnings.warn('Scientific colormaps not found. Install with `conda install cmcrameri` if desired.', ImportWarning)
172        return
173
174    # Remove the 'cmc.' prefix from the colormap names
175    for name in list(mpl.colormaps):
176        if name[:4]=='cmc.':
177
178            # Register the colormap without the prefix
179            try:
180                mpl.colormaps.register( mpl.colormaps[name], name=name[4:] )
181            except ValueError:
182                pass
183            
184            # Unregister the original colormap
185            if noprefix:
186                mpl.colormaps.unregister(name)
187
188###
189_rcParams_old = mpl.rcParams.copy()
190load_fonts()
191load_crameri_colormaps()
192activate_style()
def activate_style(grid=True, gridaxis='both', mathfont='regular'):
33def activate_style(grid=True,gridaxis='both',mathfont='regular'):
34    '''Activate style sheet 
35    
36    Parameters
37    ----------
38    grid : bool, default=True
39        turn grid lines on (True) or off (False)
40    gridaxis : str, default='both'
41        specifies which axes should have grid lines
42    mathfont : str, default='regular'
43        sets font used in mathtext, 'regular' uses same font as regular text.
44        see `set_mathfont` for all options
45    '''
46    # Load settings from style file
47    mstyle.use(os.path.join(_PATH,'acgc.mplstyle'))
48
49    # Set mathtext font
50    set_mathfont(mathfont)
51
52    # Turn grid on or off
53    if grid:
54        grid_on(axis=gridaxis)
55
56    # Use high quality for inline images; Only use this if the inline backend is active
57    # 'png' is default, 'svg' is also good
58    if 'inline' in mpl.get_backend():
59        matplotlib_inline.backend_inline.set_matplotlib_formats('retina')

Activate style sheet

Parameters
  • grid (bool, default=True): turn grid lines on (True) or off (False)
  • gridaxis (str, default='both'): specifies which axes should have grid lines
  • mathfont (str, default='regular'): sets font used in mathtext, 'regular' uses same font as regular text. see set_mathfont for all options
def deactivate_style():
61def deactivate_style():
62    '''Restore rcParams prior to importing figstyle'''
63    mpl.rcParams = _rcParams_old

Restore rcParams prior to importing figstyle

def set_mathfont(fontname=None):
 65def set_mathfont(fontname=None):
 66    '''Set the font used for typsetting math in Matplotlib
 67
 68    Parameters
 69    ----------
 70    fontname : str, default=None
 71        Should be one of
 72        - None         : Restore mathtext font to settings before importing figstyle
 73        - 'regular'    : Use same font as regular text in math expressions (default).
 74                       Same as using \\mathregular or \\mathdefault in math expressions.
 75                       Best for mixing regular and math text for superscripts and subscripts.
 76                       May lack or have poor positioning of some math symbols (e.g. integrals).
 77                       This will overwrite mathtext.bf, mathtext.bfit, mathtext.it, 
 78                       mathtext.rm in rcParams.
 79        - 'custom'     : Uses custom settings from rcParams (mathtext.bf, .bfit, .it, .rm)
 80        - 'cm'         : Computer Modern (i.e. LaTeX default)
 81        - 'stix'       : STIX serif
 82        - 'stixsans'   : STIX sans-serif; best for sans-serif math
 83        - 'dejavuserif': DejaVu Serif (not recommended)
 84        - 'dejavusans' : DejaVu Sans (not recommended)
 85    '''
 86
 87    # Check that input has an allowed value
 88    allowedvalues = ['None','regular','custom','cm','stix','stixsans','dejavusans','dejavuserif']
 89    if (fontname not in allowedvalues) and (fontname is not None):
 90        raise ValueError('Font name should be one of the allowed values: '+','.join(allowedvalues))
 91
 92    if fontname is None:
 93        # Restore old mathtext settings
 94        mpl.rcParams.update( {key:_rcParams_old[key] for key in
 95                              ['mathtext.fontset','mathtext.bf','mathtext.bfit',
 96                               'mathtext.it','mathtext.rm']})
 97
 98    elif fontname == 'regular':
 99        # Set the math font to the font used for regular text
100
101        # Name of the text font
102        textfont = mpl.rcParams[f'font.{mpl.rcParams["font.family"][0]:s}'][0]
103        # Use the same font for math
104        mpl.rcParams.update({'mathtext.fontset': 'custom',
105                            'mathtext.bf'   : f'{textfont}:bold',
106                            'mathtext.bfit' : f'{textfont}:italic:bold',
107                            'mathtext.it'   : f'{textfont}:italic',
108                            'mathtext.rm'   : f'{textfont}'})
109    else:
110        # Set the math font to the value provided
111        mpl.rcParams['mathtext.fontset'] = fontname

Set the font used for typsetting math in Matplotlib

Parameters
  • fontname (str, default=None): Should be one of
    • None : Restore mathtext font to settings before importing figstyle
    • 'regular' : Use same font as regular text in math expressions (default). Same as using \mathregular or \mathdefault in math expressions. Best for mixing regular and math text for superscripts and subscripts. May lack or have poor positioning of some math symbols (e.g. integrals). This will overwrite mathtext.bf, mathtext.bfit, mathtext.it, mathtext.rm in rcParams.
    • 'custom' : Uses custom settings from rcParams (mathtext.bf, .bfit, .it, .rm)
    • 'cm' : Computer Modern (i.e. LaTeX default)
    • 'stix' : STIX serif
    • 'stixsans' : STIX sans-serif; best for sans-serif math
    • 'dejavuserif': DejaVu Serif (not recommended)
    • 'dejavusans' : DejaVu Sans (not recommended)
def grid_off():
113def grid_off():
114    '''Turn off grid lines'''
115    mpl.rcParams['axes.grid'] = False

Turn off grid lines

def grid_on(axis='both'):
117def grid_on(axis='both'):
118    '''Turn on grid lines
119    
120    Parameters
121    ----------
122    axis : {'both', 'x', 'y'}
123        specifies which axes should have grid lines 
124    '''
125    mpl.rcParams['axes.grid'] = True
126    mpl.rcParams['axes.grid.axis'] = axis

Turn on grid lines

Parameters
  • axis ({'both', 'x', 'y'}): specifies which axes should have grid lines
def load_fonts():
128def load_fonts():
129    '''Load fonts contained in the acgc/fonts subdirectory'''
130
131    # User fonts
132    fonts_pylib = mfonts.findSystemFonts(os.path.join(_PATH,'fonts'))
133
134    # Cached fonts
135    fonts_cached = mfonts.fontManager.ttflist
136    fonts_cached_paths = [ font.fname for font in fonts_cached ]
137
138    # Add fonts that aren't already installed
139    rebuild = False
140    for font in fonts_pylib:
141        if font not in fonts_cached_paths:
142            if rebuild is False:
143                # Issue warning, first time only
144                warnings.warn('Rebuilding font cache. This can take time.')
145            rebuild = True
146            mfonts.fontManager.addfont(font)
147
148    # Save font cache
149    if rebuild:
150        cache = os.path.join(
151                        mpl.get_cachedir(),
152                        f'fontlist-v{mfonts.FontManager.__version__}.json'
153                    )
154        mfonts.json_dump(mfonts.fontManager, cache)

Load fonts contained in the acgc/fonts subdirectory

def load_crameri_colormaps(noprefix=True):
156def load_crameri_colormaps(noprefix=True):
157    '''Load Fabio Crameri's Scientific color maps
158
159    https://www.fabiocrameri.ch/colourmaps/
160    https://github.com/callumrollo/cmcrameri
161    
162    Parameters
163    ----------
164    noprefix : bool, default=True
165        If True, remove the 'cmc.' prefix from the colormap names
166    '''
167
168    # Import the colormaps; The registered names will be prefixed with 'cmc.'
169    try:
170        from cmcrameri import cm
171    except ImportError:
172        warnings.warn('Scientific colormaps not found. Install with `conda install cmcrameri` if desired.', ImportWarning)
173        return
174
175    # Remove the 'cmc.' prefix from the colormap names
176    for name in list(mpl.colormaps):
177        if name[:4]=='cmc.':
178
179            # Register the colormap without the prefix
180            try:
181                mpl.colormaps.register( mpl.colormaps[name], name=name[4:] )
182            except ValueError:
183                pass
184            
185            # Unregister the original colormap
186            if noprefix:
187                mpl.colormaps.unregister(name)

Load Fabio Crameri's Scientific color maps

https://www.fabiocrameri.ch/colourmaps/ https://github.com/callumrollo/cmcrameri

Parameters
  • noprefix (bool, default=True): If True, remove the 'cmc.' prefix from the colormap names