I\'m using Python to plot several straight lines on the same plot.
I have a great variability in values magnitude over x values (called with variable q
in my c
As said in the comments, when manipulating scale to show uneven spacings, straight lines would not be as straight lines any more.
Below is a code that implements a scale like desired in the question.
import numpy as np
from numpy import ma
from matplotlib import scale as mscale
from matplotlib import transforms as mtransforms
from matplotlib.ticker import FixedLocator
class SegmentedScale(mscale.ScaleBase):
name = 'segmented'
def __init__(self, axis, **kwargs):
mscale.ScaleBase.__init__(self)
self.points = kwargs.get('points',[0,1])
self.lb = self.points[0]
self.ub = self.points[-1]
def get_transform(self):
return self.SegTrans(self.lb, self.ub, self.points)
def set_default_locators_and_formatters(self, axis):
axis.set_major_locator(FixedLocator(self.points))
def limit_range_for_scale(self, vmin, vmax, minpos):
return max(vmin, self.lb), min(vmax, self.ub)
class SegTrans(mtransforms.Transform):
input_dims = 1
output_dims = 1
is_separable = True
def __init__(self, lb, ub, points):
mtransforms.Transform.__init__(self)
self.lb = lb
self.ub = ub
self.points = points
def transform_non_affine(self, a):
masked = a # ma.masked_where((a < self.lb) | (a > self.ub), a)
return np.interp(masked, self.points, np.arange(len(self.points)))
def inverted(self):
return SegmentedScale.InvertedSegTrans(self.lb, self.ub, self.points)
class InvertedSegTrans(SegTrans):
def transform_non_affine(self, a):
return np.interp(a, np.arange(len(self.points)), self.points)
def inverted(self):
return SegmentedScale.SegTrans(self.lb, self.ub, self.points)
# Now that the Scale class has been defined, it must be registered so
# that ``matplotlib`` can find it.
mscale.register_scale(SegmentedScale)
if __name__ == '__main__':
u= u"""0, 137.13, 0.082
0.1, 112.46, 0.175
0.2, 98.23, 0.368
0.5, 72.38, 0.838
1, 60.69, 8.932
10, 54.21, 17.602
20, 47.71, 48.355
50, 46.14, 89.358
100, 41.23, 241.147
250, 39.77, 0"""
import io
import matplotlib.pyplot as plt
q,r,breakpoints = np.loadtxt(io.StringIO(u), delimiter=", ", unpack=True)
c = lambda m,x : m*x
for i in range(0,9):
w = np.arange(0., q[9], 0.01)
plt.plot(w,c(r[i],w),'b--',linewidth=0.3)
plt.plot( [q[i],breakpoints[i]] , [c(r[i], q[i]), c(r[i], breakpoints[i])], 'r')
plt.plot(q[i + 1], c(r[i], breakpoints[i]), 'r.')
plt.gca().set_xscale('segmented', points = q)
plt.show()
Apart from the kinks in the lines, which might not be desired, but are a necessary consequence from the kind of scale used here, the values on the y axis are still quite unreadable.