From: Axel Freyn <freynaxe@us...>  20101203 18:30:08

Hi Will, On Fri, Dec 03, 2010 at 11:49:20AM 0600, William Henney wrote: > Hi list > > I am trying to produce a vector plot with pyx.graph.style.arrow() in > which the arrow heads do not appear. > > The only working solution I have found is to put > > pyx.graph.style.arrow(arrowattrs=[pyx.color.transparency(1.0)]) > > but this does not seem like a "clean" solution. > > The following two attempted solutions did not work: > > 1. pyx.graph.style.arrow(arrowattrs=[attr.clear]) > > File "/Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/sitepackages/pyx/deco.py", > line 240, in processPDF > raise RuntimeError("Path neither to be stroked nor filled nor > decorated in another way") > > 2. pyx.graph.style.arrow(arrowsize=0) > > File "/Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/sitepackages/pyx/normpath.py", > line 957, in close > raise NormpathException("Normsubpath too short, cannot be closed") > > Is there a better way than transparency to achieve this? The reason I > don't want arrow heads is that the field I am plotting is of > polarization "vectors", for which there is no distinction between the > angle theta and the angle (theta + 180 deg). Well, the cleanest way I see would be to clone the graph.style.arrowclass and create a new plotstyle which does not plot an arrow (I call it "arrow_line"). By deriving it from the class "graph.style.arrow", it behaces exactly as that class. So I only overwrite one function: the one, which draws the lines+arrows. This function is a copy from the original function where I just removed the arrow ;) from pyx import * import math # derive the class from graph.style.arrow class arrow_line(graph.style.arrow): # overload only the plotfunction def drawpoint(self, privatedata, sharedata, graph, point): if privatedata.lineattrs is not None and privatedata.arrowattrs is not None and sharedata.vposvalid: linelength_pt = unit.topt(self.linelength) x_pt, y_pt = graph.vpos_pt(*sharedata.vpos) try: angle = point["angle"] + 0.0 size = point["size"] + 0.0 except: pass else: if point["size"] > self.epsilon: dx = math.cos(angle*math.pi/180) dy = math.sin(angle*math.pi/180) x1 = x_ptself.arrowpos*dx*linelength_pt*size y1 = y_ptself.arrowpos*dy*linelength_pt*size x2 = x_pt+(1self.arrowpos)*dx*linelength_pt*size y2 = y_pt+(1self.arrowpos)*dy*linelength_pt*size privatedata.arrowcanvas.stroke(path.line_pt(x1, y1,x2, y2), privatedata.lineattrs) # test & use ist: # just some data to plot d = [ [i,j,(i+j)/10.,2*math.pi/10.*i] for i in range(10) for j in range(10)] # the graph... g = graph.graphxy(width=10) g.plot(graph.data.points(d,x=1,y=2,size=3,angle=4),[arrow_line()]) g.writePDFfile("p") (Of course this code is not 100% clean: You can pass the argument "arrowsize" to my new class "arrow_line", which is quite stupid... From that point of view, it would be cleaner to rewrite the complete class. And the most powerfull solution would be a new arrowclass in pyx, where the arrow can be passed as parameter ;)) Axel 