0

I have a function defined on the interval [0,1) (all numbers ranging from 0 to 1 excluding 1), which has some erratic behaviour around 1, for example the function f = lambda x : 1 / (1-x). I can plot it using:

import matplotlib.pyplot as plt
x_range = np.linspace(0,1,num=100)
plt.plot(x_range, f(x_range))
plt.show()

If the asymptotic behaviour was at 0, we would simply use a logarithmic x scale but now the asymptote is at 1 therefore we would like to have a logarithmic scale around 1, our scale could for example be : 1 - 10^0, 1 - 10^1, 1 - 10^2, 1 - 10^3, ....

EDIT : I just discovered this link so I guess I can make my own scale which I am currently trying to do.

Using the link provided in the comments I got the following 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 1 - 10 **(-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 -np.log10(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 = np.linspace(0,0.9999,num = 100)
thick = 1/(1-z)

fig = plt.figure(figsize=(8,5))
ax1 = fig.add_subplot(111)
ax1.plot(z, thick, 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()

which is not exactly as expected so I guess I made a mistake setting the transform.

Darkwizie
  • 147
  • 4
  • As it stands this seems very generic and I would hence close this as duplicate of [this question](https://stackoverflow.com/questions/43463431/custom-logarithmic-axis-scaling-in-matplotlib), which shows how to do a custom scaling (for a logarithmic axes). In case you have trouble implementing this, you would want to refine your question with the *actual* problem. – ImportanceOfBeingErnest Feb 07 '18 at 14:44
  • Could you please tell exactly what you get and in how far this is not what you expect? – ImportanceOfBeingErnest Feb 08 '18 at 16:01
  • I see what you mean. You just confused the transformation direction. The transform itself should have `-np.log10(1-a)` and its inverse should be `1 - 10 **(-a)`. – ImportanceOfBeingErnest Feb 08 '18 at 16:31
  • If I change them, I get `ValueError: posx and posy should be finite values` – Darkwizie Feb 08 '18 at 22:47
  • But if you want a scaled log scale the transform needs to have the log in it. Can you please update the question with the code and the *full* error traceback. Also what version of matplotlib are you using? – ImportanceOfBeingErnest Feb 08 '18 at 22:54

0 Answers0