8

I've been python code to plot 4 figures with colorbars. Since I use Texfonts, matplotlib renders the minus sign too wide. I therefore have a written a formatting function to replace the minus sign with a hyphen. However, for some reason I can't apply the formatter to my colorbar. I am getting an error:

cb.ax.set_major_formatter(ticker.FuncFormatter(myfmt))
AttributeError: 'AxesSubplot' object has no attribute 'set_major_formatter'

So below is the portion of my code where it breaks: Do you have an idea how to force the colorbar to use my formatting function?

#!/usr/bin/env python3 

import re
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc 
from matplotlib.ticker import *
import matplotlib.ticker as ticker
import matplotlib as mpl
import matplotlib.gridspec as gridspec
from matplotlib.patches import Ellipse
from list2nparr import list2nparr
from matplotlib.ticker import ScalarFormatter 

plt.rcParams['text.usetex'] = True
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = 'cm'
plt.rcParams['font.size'] = 16
#plt.rcParams['font.weight'] = 'heavy'
plt.rcParams['axes.unicode_minus'] = False
#-----------------------------------------------------


def myfmt(x, pos=None):
  rv = format(x)
  if mpl.rcParams["text.usetex"]:
    rv = re.sub('$-$', r'\mhyphen', rv)

  return rv


fig,(ax1,ax2,ax3,ax4) = plt.subplots(nrows=4,figsize=(6,11),sharex = True, sharey=False)
data = list2nparr('radiant.txt')

lm  = data[:,14]
bet = data[:,15]
v   = data[:,16]
b   = data[:,18]
ejep = data[:,20]

fig.subplots_adjust(hspace=0.1)

cm = plt.cm.get_cmap('jet') 
sc = ax1.scatter(lm, bet, c=ejep, s=10, cmap=cm, edgecolor='none',rasterized=True)
cb=plt.colorbar(sc,ax = ax1,aspect=10)
cb.formatter.set_powerlimits((0, 0))
cb.ax.set_major_formatter(ticker.FuncFormatter(myfmt))
cb.update_ticks()
user3578925
  • 881
  • 3
  • 16
  • 26
  • Possible duplicate of [Matplotlib log-scale tick labels, minus sign too long in latex font](http://stackoverflow.com/questions/25210898/matplotlib-log-scale-tick-labels-minus-sign-too-long-in-latex-font) – tmdavison Dec 26 '15 at 08:44

2 Answers2

5

You need to specify the xaxis:

cb.ax.xaxis.set_major_formatter(plt.FuncFormatter(myfmt))

or yaxis:

cb.ax.yaxis.set_major_formatter(plt.FuncFormatter(myfmt))

when setting the formatter.

Mike Müller
  • 82,630
  • 20
  • 166
  • 161
  • I changed the line in my code from: cb.ax.set_major_formatter(ticker.FuncFormatter(myfmt)) to: cb.ax.yaxis.set_major_formatter(ticker.FuncFormatter(myfmt)) Now it runs smoothly without any errors but I noticed that it does not call the function at all. I put a line in my functions "print(rv)" and it does not print anything and the minus sign is still too big. – user3578925 Dec 25 '15 at 15:24
  • `plt.FuncFormatter(myfmt)` works or me as well as `ticker.FuncFormatter(myfmt)`. Double check that you actually hand in the right function. – Mike Müller Dec 25 '15 at 15:44
  • I changed the line to: `cb.ax.yaxis.set_major_formatter(plt.FuncFormatter(myfmt))` but still no effect. The function does not seem to be called at all, as it does not print anything. Plus the minus sign in the figure is still unchanged. – user3578925 Dec 25 '15 at 15:52
  • I would like to clarify that, if change the line: `cb=plt.colorbar(sc,ax = ax1,aspect=10)` to `cb=plt.colorbar(sc,ax = ax1,aspect=10,format=ticker.FuncFormatter(myfmt))` and disable the line `#cb.formatter.set_powerlimits((0, 0))` it works - changing the minus sign to hyphen but then I lose the exponent being placed at the top of the colorbar. However, if I enable the line `cb.formatter.set_powerlimits((0, 0))` I am getting the following error: `cb.formatter.set_powerlimits((0, 0)) AttributeError: 'FuncFormatter' object has no attribute 'set_powerlimits'` – user3578925 Dec 25 '15 at 16:03
0

I found the answer in the following post: in the following post.

The solution is, instead of using LogFormatter one has to change the function to ScalarFormatter and define the \mhyphen as:

plt.rcParams["text.latex.preamble"].append(r'\mathchardef\mhyphen="2D')

So the following definition of the class worked for me:

class Myfmt(mpl.ticker.ScalarFormatter):
    def __call__(self, x, pos=None):
        # call the original LogFormatter
        rv =mpl.ticker.ScalarFormatter.__call__(self, x, pos)

        # check if we really use TeX
        if mpl.rcParams["text.usetex"]:
            # if we have the string ^{- there is a negative exponent
            # where the minus sign is replaced by the short hyphen
            rv = re.sub('-', r'\mhyphen', rv)

        return rv

Then I just changed the line:

cb=plt.colorbar(sc,ax = ax1,aspect=10)

to

cb=plt.colorbar(sc,ax = ax1,aspect=10,format=Myfmt())

and I also enabled the line for placing a single exponent at the top of the colorbar:

cb.formatter.set_powerlimits((0, 0))

Thank you for for helping me to find the answer!

Community
  • 1
  • 1
user3578925
  • 881
  • 3
  • 16
  • 26