From: André W. <wo...@us...> - 2010-10-27 19:59:22
|
Am 27.10.2010 um 21:10 schrieb Stefan Schenk: > Am Mittwoch, 27. Oktober 2010, 16:34:56 schrieb Mico Filós: >> I have an array containing N points (x, y, r), where x is an >> abscissa, y is an ordinate, and r is a real between 0 and 1. I would >> like to plot the the array {(x, y)} as a continuous path, using the >> sequence of r's as the normalized gray value at each particular >> point. This is not hard if data points are plotted with symbols, >> but I want to use the line style for data points, taking the >> sequence of N r's as the (externally defined) color gradient for >> the curve defined by {(x, y)}. >> It sounds more complicated than it really is. Any ideas? > > I don't see an easy way to do this. What makes this even more complex is > that with lines your third dimension (r) is not well defined. For points > you can always assign a color to the point, but a line lives between two > points. What color do you assign to the line? > > Of course there are complicated ways to do something like this: > The most straightforward way I can think of at the moment is to create > the paths between the points by hand, then splitting these paths and > then drawing each of these subpaths with colors according to the colors > at your points. You are right, Stefan. I'm not aware of a possibility to alter the color of a line either. However, we can go along the line of splitting the each line manually and alter the color as needed. And, this is PyX, where you can introduce such a graph style by just a couple of lines. Here we go: -------------------- from pyx import * class gradientline(graph.style.line): def __init__(self, colorcolumnname="color", colorprecision=100, gradient=color.gradient.Gray, **kwargs): self.colorcolumnname = colorcolumnname self.colorprecision = colorprecision self.gradient = gradient graph.style.line.__init__(self, **kwargs) def columnnames(self, privatedata, sharedata, agraph, columnnames): if self.colorcolumnname not in columnnames: raise ValueError("column '%s' missing" % self.colorcolumnname) return ([self.colorcolumnname] + graph.style.line.columnnames(self, privatedata, sharedata, agraph, columnnames)) def initdrawpoints(self, privatedata, sharedata, graph): privatedata.color = None def drawpoint(self, privatedata, sharedata, graph, point): if privatedata.color is not None: self.addpoint(privatedata, graph.vpos_pt, sharedata.vposavailable, sharedata.vposvalid, sharedata.vpos) path = self.donepointstopath(privatedata) if privatedata.lineattrs is not None and len(path): splits = int(abs(point[self.colorcolumnname] - privatedata.color)*self.colorprecision) if splits: path = path.normpath() arclen_pt = path.arclen_pt() segments = path.split_pt([(i+1)*arclen_pt/(splits+1) for i in range(splits)]) for i, segment in enumerate(segments): graph.stroke(segment, privatedata.lineattrs + [self.gradient.getcolor(privatedata.color + (point[self.colorcolumnname]-privatedata.color)*(i+0.5)/splits)]) else: graph.stroke(path, privatedata.lineattrs + [self.gradient.getcolor(point[self.colorcolumnname])]) self.initpointstopath(privatedata) self.addpoint(privatedata, graph.vpos_pt, sharedata.vposavailable, sharedata.vposvalid, sharedata.vpos) privatedata.color = point[self.colorcolumnname] def donedrawpoints(self, privatedata, sharedata, graph): pass g = graph.graphxy(width=10) g.plot(graph.data.points([[random.random() for i in range(3)] for i in range(10)], x=1, y=2, color=3), [gradientline(gradient=color.gradient.Rainbow)]) g.writePDFfile() -------------------- André -- by _ _ _ Dr. André Wobst, Amselweg 22, 85716 Unterschleißheim / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |