From: Tom Kornack <tom@ko...>  20080612 16:31:15
Attachments:
Message as HTML

Dear PyX experts: I am seeking a way to make the y2 axis a (continuous, monotonic) algebraic function of the y axis. Nearly three years ago, I sought to do this and received the attached solution, which worked great with PyX 0.7. However, in the intervening time it would appear that the internals of PyX have changed somewhat and the following solution not longer seems to work for me. In particular, there is no longer an invert method for the axes. I'm curious if anyone can help me with how to do this with the latest release. Thank you, André, Jörg and Michael, for producing such a wonderful tool. Tom On 08.07.05, Andre Wobst wrote: On 08.07.05, Tom Kornack wrote: > I often use y and y2 axes on my graphs. I'm curious if there is a way > to specify the y2 axis as a function of the y axis? I am particularly > interested in cases where the axes are not linearly related but are > nonetheless monotonic. In the case that I am currently working on, > the axes are related by y2 = y/(y+a) where a is a constant. Please > let me know if this may be possible at any level of (in)elegance. Well, its a quite complicated problem as soon as you do not fix the axis ranges. The problem is, that for unfixed axis ranges, the partitioning can have some influence on the axis range. So to make a simple solution, we fix the axis ranges and go for it. Than you can do the following (on top of PyX 0.7.1): from pyx import * class relatedaxis(object, graph.axis.lin): def __init__(self, otheraxis, a, **kwargs): self.otheraxis = otheraxis self.a = a graph.axis.lin.__init__(self, **kwargs) def convert(self, value): return self.otheraxis.convert(self.a*float(value)/(1.0float(value))) def invert(self, value): otherinvert = self.otheraxis.invert(value) return otherinvert/(otherinvert + self.a) min = property(lambda self: self.invert(0), lambda self, min: None) max = property(lambda self: self.invert(1), lambda self, max: None) yaxis = graph.axis.lin(min=0, max=1) y2axis = relatedaxis(yaxis, 1) g = graph.graphxy(width=8, y=yaxis, y2=y2axis, x=graph.axis.lin(min=0, max=0.5)) g.plot(graph.data.function("y2=x")) g.writeEPSfile("relatedaxis") The y2 axis is full functional except that its ranges do completely depend on the y axis. Another difficult thing is to get a proper axis partitioning for this case. You can use the autolinearparter (i.e. the default), but I'm not sure whether equal distant ticks (in y2values) are the right thing for you. Unfortunately you can't use the autologarithmicparter (not just because we have a zero at the axis in our example above, but also because the convert method always fails for value=1). However, you can always place manual ticks and set parter to None, or you can write your own (automatic) parter. 
From: Tom Kornack <tom@ko...>  20080621 13:12:31
Attachments:
Message as HTML

Dear pyx experts: I'm curious if there is a way > to specify the y2 axis as a function of the y axis? I am particularly > interested in cases where the axes are not linearly related but are > nonetheless monotonic. In the case that I am currently working on, > the axes are related by y2 = y/(y+a) where a is a constant. Please > let me know if this may be possible at any level of (in)elegance. On 08.07.05, Andre Wobst wrote: On 08.07.05, Tom Kornack wrote: > I often use y and y2 axes on my graphs. I'm curious if there is a way > to specify the y2 axis as a function of the y axis? I am particularly > interested in cases where the axes are not linearly related but are > nonetheless monotonic. In the case that I am currently working on, > the axes are related by y2 = y/(y+a) where a is a constant. Please > let me know if this may be possible at any level of (in)elegance. Well, its a quite complicated problem as soon as you do not fix the axis ranges. The problem is, that for unfixed axis ranges, the partitioning can have some influence on the axis range. So to make a simple solution, we fix the axis ranges and go for it. Than you can do the following (on top of PyX 0.7.1): from pyx import * class relatedaxis(object, graph.axis.lin): def __init__(self, otheraxis, a, **kwargs): self.otheraxis = otheraxis self.a = a graph.axis.lin.__init__(self, **kwargs) def convert(self, value): return self.otheraxis.convert(self.a*float(value)/(1.0float(value))) def invert(self, value): otherinvert = self.otheraxis.invert(value) return otherinvert/(otherinvert + self.a) min = property(lambda self: self.invert(0), lambda self, min: None) max = property(lambda self: self.invert(1), lambda self, max: None) yaxis = graph.axis.lin(min=0, max=1) y2axis = relatedaxis(yaxis, 1) g = graph.graphxy(width=8, y=yaxis, y2=y2axis, x=graph.axis.lin(min=0, max=0.5)) g.plot(graph.data.function("y2=x")) g.writeEPSfile("relatedaxis") The y2 axis is full functional except that its ranges do completely depend on the y axis. Another difficult thing is to get a proper axis partitioning for this case. You can use the autolinearparter (i.e. the default), but I'm not sure whether equal distant ticks (in y2values) are the right thing for you. Unfortunately you can't use the autologarithmicparter (not just because we have a zero at the axis in our example above, but also because the convert method always fails for value=1). However, you can always place manual ticks and set parter to None, or you can write your own (automatic) parter. 