From: John O. <joh...@ya...> - 2006-05-26 06:30:46
|
functionpalette looks like a terrific function. Could you provide a minimal example of how it is used? The proximate reason I'm asking is that the default palettes are, well, kind of strong, and good graphs typically use more harmonious colors. I'd like to see PyX use and support the ColorBrewer (colorbrewer.org) schemes for colors, and functionpalette is perfect for this, and if I can get an example of how it's used I'll try it out. JDO __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com |
From: John O. <joh...@ya...> - 2006-05-26 07:19:18
|
Actually, might I follow up to this and instead ask: Can I get an example of a palette that's not a built-in palette? It's the palette.select call that I think I really need to support here. JDO --- John Owens <joh...@ya...> wrote: > functionpalette looks like a terrific function. Could you provide a minimal > example of how it is used? > > The proximate reason I'm asking is that the default palettes are, well, kind > of > strong, and good graphs typically use more harmonious colors. I'd like to see > PyX use and support the ColorBrewer (colorbrewer.org) schemes for colors, and > functionpalette is perfect for this, and if I can get an example of how it's > used I'll try it out. > > JDO > > __________________________________________________ > Do You Yahoo!? > Tired of spam? Yahoo! Mail has the best spam protection around > http://mail.yahoo.com > __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com |
From: Michael S. <mic...@ph...> - 2006-05-26 08:24:31
|
Hello John, On 26.05.06, John Owens wrote: > Actually, might I follow up to this and instead ask: > > Can I get an example of a palette that's not a built-in palette? It's the > palette.select call that I think I really need to support here. Yes. I had not yet received this mail when answering the previous one. Here is a self-contained example: import math from pyx import * def red(x): return math.sin(x / math.pi) def green(x): return x def blue(x): return x**2 pal = color.functionpalette(functions={"r":red, "g":green, "b":blue}, type="rgb") c = canvas.canvas() c.fill(path.rect(0, 0, 1, 1), [pal.getcolor(0.3)]) c.fill(path.rect(1, 0, 1, 1), [pal.getcolor(0.6)]) c.fill(path.rect(2, 0, 1, 1), [pal.getcolor(0.0)]) c.fill(path.rect(3, 0, 1, 1), [pal.getcolor(1.0)]) c.writeEPSfile("mini", paperformat=document.paperformat.A4) You can ask 'pal' for a color with the 'getcolor' method. Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |
From: Andre W. <wo...@us...> - 2006-05-26 08:33:36
|
Hi, On 26.05.06, John Owens wrote: > Can I get an example of a palette that's not a built-in palette? It's the > palette.select call that I think I really need to support here. Just an additional note to hopefully clearify certain issues: select is an method needed for changeable attributes (in the graph system). We have not yet documented all that functionality and (at least for the moment) I would not count that to be an external interface. getcolor however is. Note that a palette (currently) is not a discrete thing (except within the select functionality in the graph system). However, it sounds reasonable to create indexed color spaces based on palettes. Such a feature is likely to be added at some later time ... André -- by _ _ _ Dr. André Wobst / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: John O. <joh...@ya...> - 2006-05-26 23:46:55
|
--- John Owens <joh...@ya...> wrote: > Can I get an example of a palette that's not a built-in palette? It's the > palette.select call that I think I really need to support here. Sourceforge is appearing to take many many hours for emails to show up, so I'm replying here without having seen more than the 6 messages already on the sf.net mailing list page. Sorry if I've missed anything. Here's the support I want to add. palette.select() appears to be the right interface for it, I think, so that's specifically what I'm hoping to see sample code for. The folks at colorbrewer.org have spent a lot of time finding good palettes for drawing. The interface is palette[name][number], where 'name' is a specific palette ("accent", "blues", etc.) and 'number' is the number of different items that need to be drawn. That's exactly what select() does. I'd like to create a data structure that looks something like: palette['accent'][3] = [ rgb(RR, GG, BB), rgb(RR, GG, BB), rgb(RR, GG, BB) ] palette['accent'][4] = [ rgb(RR, GG, BB), rgb(RR, GG, BB), rgb(RR, GG, BB), rgb(RR, GG, BB) ] ... where I fill in all the RR, GG, and BBs. But I don't know how to use the select call (or another call) that will let the palette automatically choose the right 'number' based on the number of drawn items and then pick the right colors from that. I'm happy to convert the colorbrewer schemes so they work and then contribute them to the codebase if I can get some help on this. JDO __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com |
From: Michael S. <mic...@ph...> - 2006-06-05 22:00:09
|
Hello John, On 26.05.06, John Owens wrote: > --- John Owens <joh...@ya...> wrote: > > Here's the support I want to add. palette.select() appears to be the right > interface for it, I think, so that's specifically what I'm hoping to see sample > code for. > The folks at colorbrewer.org have spent a lot of time finding good palettes > for drawing. The interface is palette[name][number], where 'name' is a > specific palette ("accent", "blues", etc.) and 'number' is the number of > different items that need to be drawn. That's exactly what select() does. > > I'd like to create a data structure that looks something like: > > palette['accent'][3] = [ rgb(RR, GG, BB), rgb(RR, GG, BB), rgb(RR, GG, BB) ] > palette['accent'][4] = [ rgb(RR, GG, BB), rgb(RR, GG, BB), rgb(RR, GG, BB), > rgb(RR, GG, BB) ] > ... > where I fill in all the RR, GG, and BBs. But I don't know how to use the > select call (or another call) that will let the palette automatically choose > the right 'number' based on the number of drawn items and then pick > the right colors from that. All PyX palettes internally use a real parameter between 0 and 1. The color values are defined in terms of continuous functions. What you want to do here, is rather a discrete definition of the palette. In order to convince PyX to use your color values, you have to do the following: Define functions function which interpolates all the RGB values from colorbrewer. This can either be a simple piecewise linear function or, better, a smooth approximation to it. Then take these three functions (one for each RGB value) and define a functionpalette with it, call it "accentpalette", if you like. Instead of palette['accent'][3] you have to say accentpalette.select(3, N) where N is the total number of colors you need from the palette. Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |
From: John O. <joh...@ya...> - 2006-06-06 19:07:16
|
Michael Schindler <michael.schindler <at> physik.uni-augsburg.de> writes: > All PyX palettes internally use a real parameter between 0 and 1. The > color values are defined in terms of continuous functions. What you > want to do here, is rather a discrete definition of the palette. Exactly. And it seems like this would be a useful addition to have, that palettes ought to support a discrete representation. > In order to convince PyX to use your color values, you have to do the > following: Define functions function which interpolates all the RGB values > from colorbrewer. This can either be a simple piecewise linear > function or, better, a smooth approximation to it. > Then take these three functions (one for each RGB value) and define > a functionpalette with it, call it "accentpalette", if you like. The problem is that the function for 4 values is different than the function for 3 values. Think of a representation for a palette where if I want 3 values, those values are completely different than if I want 4 values, which is in turn different than 5 values, etc. Thus I don't think this technique is useful for arbitrarily defined palettes, at least not the ones that I'd like to add. (Also, it's a kludgey solution at best.) I'm happy to try to add the support to PyX itself, but what I would need explained is how the palette call gets the number of points to draw (after all the points are accumulated, their number is somehow communicated to the palette and I haven't been able to work out how that is done yet). JDO |
From: Michael S. <mic...@ph...> - 2006-05-26 07:55:50
|
Hello John, On 25.05.06, John Owens wrote: > functionpalette looks like a terrific function. Could you provide a minimal > example of how it is used? There is one pre-defined functionpalette in color.py: palette.BlackYellow A more simplistic example is the following: def red(x): return x def green(x): return x def blue(x): return x pal = color.functionpalette(functions={"r":red, "g":green, "b":blue}, type = "rgb") Here, {"r":red, "g":green, "b":blue} is a dictionary providing the r,g,b functions to evaluate the colors depending on a single parameter in the interval [0,1]. You can likewise use a dictionary with the keys c,m,y,k. > The proximate reason I'm asking is that the default palettes are, well, kind of > strong, and good graphs typically use more harmonious colors. The BlackYellow palette is optimized to yield good results print out in grayscales (this is especially important when publishing in color-online scientific journals) > I'd like to see > PyX use and support the ColorBrewer (colorbrewer.org) schemes for colors, and > functionpalette is perfect for this, and if I can get an example of how it's > used I'll try it out. If you have a palette of general interest, please do not hesitate to suggest it. We will consider to take it into PyX. Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |
From: Alan G I. <ai...@am...> - 2006-05-26 15:40:36
|
On Fri, 26 May 2006, Michael Schindler apparently wrote:=20 > The BlackYellow palette is optimized to yield good results=20 > print out in grayscales (this is especially important when=20 > publishing in color-online scientific journals)=20 Is this theory based or trial and error. If the former, can you post a reference. Thank you, Alan Isaac |
From: Michael S. <mic...@ph...> - 2006-06-05 21:52:05
|
Hello Alan, On 26.05.06, Alan G Isaac wrote: > On Fri, 26 May 2006, Michael Schindler apparently wrote: > > The BlackYellow palette is optimized to yield good results > > print out in grayscales (this is especially important when > > publishing in color-online scientific journals) > > Is this theory based or trial and error. > If the former, can you post a reference. sorry for the late answer, I was busy the last few days... The conversion of colors into grayscales is not quite straightforward. On any reasonable Postscript device, however, the conversion rule defined in the Postscript standard should be applied. This means RGB -> GRAY: GRAY = 0.3*R + 0.59*G + 0.11*B Similar things can be defined for CMYK -> GRAY. A good reference on these things is the documentation for the LaTeX package xcolor.sty. A good color palette has a linear dependence of the such defined gray value on the parameter. This is not exactly the case with BlackYellow, but nearly. You can play with differently defined palettes in the file <PYX-SVN>/design/palettetest.py Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |
From: Alan G I. <ai...@am...> - 2006-06-09 07:48:02
|
On Mon, 5 Jun 2006, Michael Schindler apparently wrote: > The conversion of colors into grayscales is not quite > straightforward. On any reasonable Postscript device, > however, the conversion rule defined in the Postscript > standard should be applied. This means > RGB -> GRAY: > GRAY = 0.3*R + 0.59*G + 0.11*B OK. Section 7.2.1 of the red book. > Similar things can be defined for CMYK -> GRAY. A good reference on > these things is the documentation for the LaTeX package xcolor.sty. http://www.tug.org/tex-archive/macros/latex/contrib/xcolor/xcolor.pdf Interesting discussions! > A good color palette has a linear dependence of the such defined gray > value on the parameter. This is not exactly the case with BlackYellow, > but nearly. You can play with differently defined palettes in the file > <PYX-SVN>/design/palettetest.py Thanks! Alan |
From: John O. <joh...@ya...> - 2006-05-27 21:40:23
|
Michael Schindler <michael.schindler <at> physik.uni-augsburg.de> writes: > > pal = color.functionpalette(functions={"r":red, "g":green, "b":blue}, type="rgb") > c.fill(path.rect(0, 0, 1, 1), [pal.getcolor(0.3)]) > c.fill(path.rect(1, 0, 1, 1), [pal.getcolor(0.6)]) > c.fill(path.rect(2, 0, 1, 1), [pal.getcolor(0.0)]) > c.fill(path.rect(3, 0, 1, 1), [pal.getcolor(1.0)]) This is a very nice example. Thank you. I think this is applicable to my needs certainly. However, I'd like to use something slightly different: instead of a single-argument getcolor function, I'd like a delayed two-argument function, where the second argument is the number of rendered points. I figure under the hood this must be used somewhere, because the getcolor arguments for a color gradient are not actually calculated until all of the calls are made. (How does this work? Clearly getcolor will take different arguments if I specify a different number of points with a gradient.) So what I really want for four points is: pal.getcolor(1, 4) pal.getcolor(2, 4) pal.getcolor(3, 4) pal.getcolor(4, 4) where the second argument is the number of points rendered (and shouldn't be calculated until all the points are specified, hence the delayed nature of the function). I can then write the functions appropriately. Any way to persuade PyX to do that? JDO |
From: Andre W. <wo...@us...> - 2006-06-10 17:23:01
|
Hi John, I'm sorry for comming back to that thread after such a long period of silence from my side. And so far I don't yet really understand your problem and what you really want to do. Let me give you some general explanations at first: Yes, we do have palettes in PyX. Palettes are tools which provide a color for a given continuous variable in range 0 to 1 by the getcolor method. That's about it for the moment. Then we have changeable attributes. These objects usually represent some stroke or fill style to be changed by request. The most simple case is a attr.changelist instance, which takes a list of style instances and returns those styles one after the other. Internally this selection is done by a select method call. A changeable attribute has such a method and this method returns the corresponding attibutes. This attribute is selected not just by a single index number, but at the same time a total number of attributes needed in this use-case of the changeable attribute is given. So the select call has the signature: select(index, total). Both are integers and index is an element of range(total). That's it. Now it's a coincidence, that a palette is a changeable attribute at the same time. Beside that we could at a certain point add a support for an indexed color space (and it's likely that I'll add this at some later point). A palette will be a good candidate for construting an indexed color space with a given number of colors. But the palette represents an infinite number of colors. On 27.05.06, John Owens wrote: > Michael Schindler <michael.schindler <at> physik.uni-augsburg.de> writes: > > > > pal = color.functionpalette(functions={"r":red, "g":green, "b":blue}, > type="rgb") > > c.fill(path.rect(0, 0, 1, 1), [pal.getcolor(0.3)]) > > c.fill(path.rect(1, 0, 1, 1), [pal.getcolor(0.6)]) > > c.fill(path.rect(2, 0, 1, 1), [pal.getcolor(0.0)]) > > c.fill(path.rect(3, 0, 1, 1), [pal.getcolor(1.0)]) BTW: I'm a strong supporter for extending the fill/stroke/draw syntax by the possibility to pass a list of paths as the first argument and then doing something similar like the plot command in the graph. You could than write: > > c.fill([path.rect(2, 0, 1, 1), > > path.rect(0, 0, 1, 1), > > path.rect(1, 0, 1, 1), > > path.rect(3, 0, 1, 1)], [pal]) The selection would than be performed "behind the scenes" as in the graph system. I think this could be very useful. (Note that I've reordered the path instances to make the selection doing the right thing.) > This is a very nice example. Thank you. I think this is applicable to my > needs certainly. However, I'd like to use something slightly different: > instead of a single-argument getcolor function, I'd like a delayed > two-argument function, where the second argument is the number of > rendered points. I figure under the hood this must be used somewhere, > because the getcolor arguments for a color gradient are not actually > calculated until all of the calls are made. (How does this work? Clearly > getcolor will take different arguments if I specify a different number of > points with a gradient.) Well, the graph does the bookkeeping. It's done within the "plotitems" instances of the graph, where all the data to be stroked is collected at first. By the way the selection of the attributes is also the reason why you can't plot further data after the dodata is performed on a graph. (We have weakened quite some of the restrictions of what can be done after already processing some parts of the graph, but the style selection is graph-global (and I do *not* propose to do something similar for the canvas in the draw/stroke/fill methods) and I very much think its best to keep this restriction. Compared to earlier restrictions, where one could easily come up with use-cases to really get into problems with them this restriction should never really harm and it allows for graph global changeable attributes ... which is a contrary feature and I think this should be prefered to be kept.) > So what I really want for four points is: > > pal.getcolor(1, 4) > pal.getcolor(2, 4) > pal.getcolor(3, 4) > pal.getcolor(4, 4) > > where the second argument is the number of points rendered (and shouldn't > be calculated until all the points are specified, hence the delayed nature > of the function). I can then write the functions appropriately. Any way to > persuade PyX to do that? Well, you can first store all point data and delay the selection until all data has been processed. Then you can just count the number of points. This is similar to what the graph is doing all the time ... HTH, André -- by _ _ _ Dr. André Wobst / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: John O. <joh...@ya...> - 2006-06-10 18:58:58
|
> Hi John, > > I'm sorry for comming back to that thread after such a long period of > silence from my side. And so far I don't yet really understand your > problem and what you really want to do. Thanks for such a long and detailed reply. I'll try to be clearer this time around. :) > Yes, we do have palettes in PyX. Palettes are tools which provide a > color for a given continuous variable in range 0 to 1 by the getcolor > method. That's about it for the moment. Understood. From a user point of view, though, I think a palette is properly a means to assign colors to a set of discrete objects. For the purposes of this note, I'll call those objects "points". So if my input is n points and one palette, I'll get back a color for each of those n points. The interface that I think the user wants, for n points, is: palette.getColor(0, n) => gives the first point's color palette.getColor(1, n) => gives the second point's color etc. Now, under the hood, that's implemented as a linear interpolation. Also, the need to specifically make that call is hidden, which is cool; it's all done under the hood as well. But somewhere in the code this calculation is made, and it's a function of the point number (first point, second point, etc.) and the total number of points. My first question, then, is where specifically is this done? I admit I haven't dived in too deep, but I'm fairly sure the linear interpolant is calculated as "point_number / total_number_of_points", and I don't know where it's done in the code. You mention to start (below) in "plotitems" so I'll start poking around there; any further pointers would be appreciated. Anyway, assuming that you do in fact make a color calculation based on the point number, the total number of points, and some data structure that you call a palette, could you generalize that calculation? Rather than a palette, I note I can use a function for each of r, g, b. That's cool. What I would like to do is a lookup table (dictionary) instead. I'd like to do color = mylookuptable[total_number_of_points][point_number]. > Well, you can first store all point data and delay the selection until > all data has been processed. Then you can just count the number of > points. This is similar to what the graph is doing all the time ... Yes, to do this I would definitely need to have the number of points. As long as the underlying system is doing this for me and calculating colors after all points are specified, though, we ought to be able to utilize that data rather than make me deal with it at the user level. Thanks. JDO |
From: Michael S. <mic...@ph...> - 2006-06-11 14:20:34
|
Hello. On 10.06.06, John Owens wrote: > Thanks for such a long and detailed reply. I'll try to be clearer this > time around. :) ;-) > palette.getColor(0, n) => gives the first point's color > palette.getColor(1, n) => gives the second point's color > etc. > > Now, under the hood, that's implemented as a linear interpolation. > Also, the need to specifically make that call is hidden, which is > cool; it's all done under the hood as well. But somewhere in the code > this calculation is made, and it's a function of the point number > (first point, second point, etc.) and the total number of points. > > My first question, then, is where specifically is this done? I admit I > haven't dived in too deep, but I'm fairly sure the linear interpolant > is calculated as "point_number / total_number_of_points", and I don't > know where it's done in the code. You mention to start (below) in > "plotitems" so I'll start poking around there; any further pointers > would be appreciated. To answer your first question: See module color.py lines 334 to 340. Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |