-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Colormap doesn't work on lines #329
Comments
Same seems to hold for |
I think I am hitting a similar issue. Here the
|
I think the issue is that categorical color variables (eg, columns of strings) are converted using the default color palette, so AlgebraOfGraphics does actually not look into For what you are looking for, you should probably do draw(plt, palettes=(color=cgrad(:Paired_4),)) (see last example here). There may still be some subtleties to take care of (for example this by default gives a regular legend rather than a colorbar, I'm not 100% sure which one you'd want), but I think those should be discussed at #183, so I'm closing this one. |
Long-term is this the right design? At least as I understand it, for continuous scales you would normally want to use |
Is the confusion that continuous and categorical scales have very different syntaxes? I think that's a fair objection, but it's not super easy to come up with a consistent solution. Do you have something in mind? IMO, allowing Conceptually, draw(plt; palettes=(...), scales=(...)) where |
I don't see why a continuous vs. discrete color space changes this: if it's confusing for continuous spaces it's confusing for discrete spaces as well. You may need different domains (one for each type of attribute) but if they map to color, I think they should all map to the same range (a mapping from number range -> linear color space). For sake of clarity here, let's call a palette a mapping from an attribute to numbers, and a colormap a mapping from said numbers to a 1d colorspace (e.g. :viridis).
I think I agree with most of this. To be concrete about how it relates to what I'm saying above about the distinction between palettes and colormaps: for palettes you'd want to specify the mapping of a domain of values to a range of integers (with some sensible default). Optionally this could also include a specification of some non-linear transform. For color mappings you'd want to specify a mapping from the same domain of numbers used in palettes to another domain of numbers representing the colors (where 0 is the first color and 1 is the last). The color mapping would be shared across all layers, while palettes could be specified on a per layer basis (or, for convenience during To be concrete, here's an example of a syntax that could makes sense to me: x = rand(100)
y = rand(100)
z = rand(["a", "b", "c", "d"], 100)
df = (; x, y, z)
plt = data(df) * mapping(:x, :y, color=:z)
colors = [colorant"#E24A33", colorant"#348ABD", colorant"#988ED5", colorant"#777777"]
color_pallete = ["a" => 1, "b" => 2]
draw(plt; color_space=(;range=colors, kind=:discrete), palettes=(;color=color_palette)) And for continuous scales: using AlgebraOfGraphics, CairoMakie
set_aog_theme!()
df = (x=randn(1000), y=randn(1000))
plt = data(df) * mapping(:x, :y) * AlgebraOfGraphics.density(npoints=50)
draw(plt * visual(Heatmap), color_space=(;range=:viridis, kind=:continuous), palettes=(;color=(0,5) => (0,1)) This would clamp density values > 5 to the same (most extreme) color. In this particular proposal I'm suggesting a keyword different than |
And, if you like this (or some variant), I'd be happy to take a crack at implementing it, at least for colors. I'm not as sure how it would relate to things like linked axes. |
Ah, I think I understand it now. You would want to split color palettes in two steps. The palette gives you integers, and the colormap turns them into colors. Reopening this because I think that proposal is not tracked anywhere. It seems like a promising idea, in that Makie would keep taking care of continuous scales, which avoids a fair amount of duplication. AlgebraOfGraphics converts categorical things into numbers. In this scenario, I suppose the default color palette should return numbers (say At this point though, one may want to reconsider the word It's probably a good occasion to also allow different attributes to use a specific "scheme". For example, how does one inform
I think your proposal is probably easier to implement than my previous rambling :), no need to worry about linked axes and such here. Especially if you want to keep the legend the same (categorical legend, as opposed to categorical colorbar legend for categorical variables) it should be reasonably straightforward. The processing of extra attributes is done in |
For plotting practice, it's probably good to offer the ability to map specific categories to integers, so that in different plots that use the same general categories, but maybe different subsets, the value => integer / color mapping stays the same. So for example, your mapping is However, it would probably be annoying having to specify this mapping for one-off plots, then it would be fine to just go 1:n with the values that are present in the specific plot. So I think the api should make this part optional. You can specify only the color list, or additionally the value => integer mapping for categorical colors. For the issue of color parameters that are not named |
Yeah, I also think this is an important use case. At the moment you can do I was also wondering, should this affect the order in which they show up in the legend? That is, if one passes ["a" => 2, "b" => 1, "c" => 3] should Re: optionality, yes, in this plan, one would have defaults for both the order (just enumerating the sorted unique values) and the color scheme (Wong colors), with the possibility of changing each independently. Mapping |
That is what I intuitively assumed. Seems reasonable, and there should be some way to manipulate order since that's a huge legibility issue. Perhaps a more principled justification is that the numbers represent some conceptual scale for the values (so it's a natural place for order to be specified). This conceptual scale is then mapped to a particular color space that has perceptual meaning.
I agree with @piever that "one would have defaults for both the order. and the color scheme". |
Nice! Yeah, maybe the right name is
I'm not certain I follow this but if I understand I think the issue here is that AoG doesn't know anything special about these attributes so you want a way to communicate that the integers should be mapped to colors (rather than say, a discrete set of linetype names or whatever). I'm not sure this is how it should be exposed as an API, but I think what this reveals is that there are really three levels:
I think one API that could make sense would be that you specify the scheme when choosing the levels. So, for example, both of the calls to plt = ... * mapping(arrowcolor=:condition) * ...
draw!(..., levels=(;arrowcolor=scheme(:color)))
draw!(..., levels=(;arrowcolor=scheme(:color, ["b" => 2, "c" => 3]))) While I think it makes sense to have this be configurable, why not have a natural default as well? For example, for any plt = ... * mapping(arrowcolor=:condition) * ...
draw!(...)
draw!(..., levels=(;arrowcolor=["b" => 2, "c" => 3])) Most of the time then, a user won't have to worry about this, but they could configure it if needed. This could lead to conflicts where a keyword maps two scheme's regexs. That could be resolved by requiring an explicit scheme for any such keyword. That is, when a keyword matches 0 or >1 regex some error gets thrown if you are trying to use |
Is this in a place where I should attempt a PR? Based on the conversation above I was thinking it might make sense to wait for a reply, but since it's been a while I'm wondering if it's worth setting up a short proof-of-concept and iterate from feedback based on something more concrete. |
It took me a little bit, but I also grew convinced that the Regarding the
draw(plt, levels=(; arrowcolor=...), scheme = :arrowcolor => :color) (with potentially some smart opt-in way to infer sensible things), but I suspect it's best to do that in a separate PR. |
Possibly it should throw an informative error in that case, as it seems weird to control only part of the levels (probably one was forgotten in the levels then?). But maybe not, I can imagine scenarios where it might be useful |
I had also initially thought one should be strict, but for instance @SimonDanisch asked for this feature: allow to have a couple of levels that are important and "fixed", and others that may vary and are not important (just cycle colors there). We currently support that with the pair syntax in the palettes. OTOH, I think it's reasonable to assume that the "explicit" levels come before the "cycled" levels in general. That way, we can get rid of the pair syntax and pass a simple list of values. |
Although one might want to mix these two cases right, let's say three fixed categories, but using colormap colors 1, 3, and 5. Then you'd still need pair syntax. |
Thinking more about this, I think there's the extra problem that the "levels" are much more a property of the data than they are a property of the plot attribute. As a practical concern, this makes it harder (and error-prone) to change what attribute is styled by a given variable, and makes it a bit more awkward to style several attributes with the same variable. Compare c = var => sorter(levels)
m = mapping(color = c, dodge = c)
draw(m * ...)
m = mapping(marker = c)
draw(m * ...) with m = mapping(color = var, dodge = var)
draw(m * ..., levels=(color=levels, dodge=levels))
m = mapping(marker = var)
draw(m * ..., levels=(marker=levels,)) Could it be enough to "power up" the |
Ah okay; so if I understand, you would never map levels to values; the palette would always be an array of colors, and any mapping of strings to numbers occurs in the |
Yes, that's correct. It seemed like the clean way to decouple ordering of categorical variables with setting the theme, though we should definitely think hard as to whether there are some important scenarios that become trickier. One situation that seems potentially troubling is the following. The user has two categorical variables (say palettes=(color=(species=[:cyan, :teal, :blue], island=[:yellow, :orange, :red]),) |
I like the notion of matching it by variable name rather than individual value. Especially because it's entirely possible that the same string could mean different things in different contexts: e.g.
|
Having looked through palettes recently, I think I understand how to implement this change; I could submit a second PR for this that also deprecates the old behavior of mapping values to colors. (Or just add it as part of #384). |
At the very least, the obvious thing you would want to do (set
colormap
in visual) doesn't seem to work.This yield output that is identical to the output when you remove
colormap
.In contrast, the following Makie-only version appropriately colors the lines.
Here's the output of
]st
The text was updated successfully, but these errors were encountered: