Escala logarítmica personalizada del eje en matplotlib

Estoy tratando de escalar el eje x de un gráfico con math.log (1 + x) en lugar de la opción de escala ‘log’ habitual, y he revisado algunos de los ejemplos de escala personalizada pero no puedo obtener el mío ¡trabajar! Aquí está mi MWE:

import matplotlib.pyplot as plt import numpy as np import math from matplotlib.ticker import FormatStrFormatter from matplotlib import scale as mscale from matplotlib import transforms as mtransforms class CustomScale(mscale.ScaleBase): name = 'custom' def __init__(self, axis, **kwargs): mscale.ScaleBase.__init__(self) self.thresh = None #thresh def get_transform(self): return self.CustomTransform(self.thresh) def set_default_locators_and_formatters(self, axis): pass class CustomTransform(mtransforms.Transform): input_dims = 1 output_dims = 1 is_separable = True def __init__(self, thresh): mtransforms.Transform.__init__(self) self.thresh = thresh def transform_non_affine(self, a): return math.log(1+a) def inverted(self): return CustomScale.InvertedCustomTransform(self.thresh) class InvertedCustomTransform(mtransforms.Transform): input_dims = 1 output_dims = 1 is_separable = True def __init__(self, thresh): mtransforms.Transform.__init__(self) self.thresh = thresh def transform_non_affine(self, a): return math.log(1+a) def inverted(self): return CustomScale.CustomTransform(self.thresh) # Now that the Scale class has been defined, it must be registered so # that ``matplotlib`` can find it. mscale.register_scale(CustomScale) z = [0,0.1,0.3,0.9,1,2,5] thick = [20,40,20,60,37,32,21] fig = plt.figure(figsize=(8,5)) ax1 = fig.add_subplot(111) ax1.plot(z, thick, marker='o', linewidth=2, c='k') plt.xlabel(r'$\rm{redshift}$', size=16) plt.ylabel(r'$\rm{thickness\ (kpc)}$', size=16) plt.gca().set_xscale('custom') plt.show() 

La escala consta de dos clases de transformación, cada una de las cuales debe proporcionar un método transform_non_affine . Una clase necesita transformarse de datos para mostrar coordenadas, que sería log(a+1) , la otra es inversa y necesita transformarse de visualización a coordenadas de datos, que en este caso sería exp(a)-1 .

Esos métodos deben manejar matrices numpy, por lo que deben usar las funciones numpy respectivas en lugar de las del paquete matemático.

 class CustomTransform(mtransforms.Transform): .... def transform_non_affine(self, a): return np.log(1+a) class InvertedCustomTransform(mtransforms.Transform): .... def transform_non_affine(self, a): return np.exp(a)-1 

introduzca la descripción de la imagen aquí