Plots.jl icon indicating copy to clipboard operation
Plots.jl copied to clipboard

[FR] Colorbar properties

Open rafaqz opened this issue 4 years ago • 46 comments

It would be useful to be able to style additional attributes of colorbars, as discussed recently on slack in plotting

~- [ ] tick size~ ~- [ ] tick color~

  • [x] ticks
  • [x] tick scale
  • [x] tick font
  • [x] tick font size
  • [x] tick font color
  • [ ] border color
  • [ ] border thickness
  • [ ] bar width
  • [ ] bar height
  • [ ] other things?

My use-case is cleaner map-plotting recipes in GeoData.jl. Currently, if you stray too far from the defaults the colorbar starts to look out of place.

This could start with just GR?

related, but just for ticks: https://github.com/JuliaPlots/Plots.jl/issues/2308

rafaqz avatar Dec 01 '20 03:12 rafaqz

It's tricky because Plots development aims to keep keywords few(-ish), in order to keep maintainability. In general all new keywords should preferably be applied across all backends to keep interchangeability of backends. One possibility could be to adapt extra_kwargs to be able to pass colorbar kwargs, but this wouldn't work in recipes. I guess this requires a bit of discussion.

@rafaqz do you happen to know how many of these attributes are supported natively by e.g. GR?

mkborregaard avatar Dec 01 '20 07:12 mkborregaard

I think the colorbar should have the same attributes as an axis. For example just like you have xticks and xscale, the colorbar should be able to support cticks and cscale. I came across this limitation while attempting cscale = :log10 (also tried zscale = :log10) on a heatmap.

hervasa2 avatar Dec 01 '20 13:12 hervasa2

I can see how keeping the keyword scope down would be important! especially given the breadth of use cases Plots.jl has to deal with.

If we can use the same set of attributes as @hervasa2 suggests, (maybe with colorbar_ prefixed?) it would at least add less overhead in terms of new names for things.

I'm not sure what is possible with GR, the colorbar method doesn't have many arguments, but there is lot of global state that is incorporated somehow. It does seem possible to do with matplotlib, plotly, and pgfplots.

rafaqz avatar Dec 02 '20 01:12 rafaqz

So having a new keyword type colorbar in addition to Plot, Subplot, Axis and Series, and reusing Axis keywords while prepending colorbar_? That does sound like a neat design. Thoughts @daschw ?

mkborregaard avatar Dec 02 '20 08:12 mkborregaard

Also I didn't read @hervasa2 comment properly, cticks etc is nice too for where x/y is usually used.

rafaqz avatar Dec 02 '20 10:12 rafaqz

So having a new keyword type colorbar in addition to Plot, Subplot, Axis and Series, and reusing Axis keywords while prepending colorbar_? That does sound like a neat design. Thoughts @daschw ?

I think that sounds like a good approach.

daschw avatar Dec 02 '20 12:12 daschw

Yes colorbar_[keyword] with c[keyword] as an alias would be nice and intuitive. I think a minimal feature in GR (if not all axis attributes can be applied to the colorbar) would be colorbar_ticks, that way the user could manipulate the data behind the scenes and set manual ticks to achieve the desired result.

hervasa2 avatar Dec 02 '20 12:12 hervasa2

There is clims at the moment

isentropic avatar Dec 02 '20 14:12 isentropic

I would also very much welcome the ability of manipulating colorbar properties. Thanks for bringing this up!

fhagemann avatar Dec 04 '20 21:12 fhagemann

I'm also looking for this functionality. Asked for exactly this in Slack and was directed here

tbeason avatar Jan 01 '21 22:01 tbeason

I think it would be nice to be able to access the frame/border/axes of the colorbar as well, e.g. colorbar_frame/cframe=:box.

bcsj avatar Jan 15 '21 09:01 bcsj

related: #2345

Gyoshi avatar Jan 21 '21 13:01 Gyoshi

If anyone is willing to help out with the development of this, please help out with the testing in the PR

isentropic avatar Mar 11 '21 08:03 isentropic

@rafaqz and others, most of the requested changes have been merged, please let me know your comments. Currently only PyPlot backend supports the new colorbar args:

    :colorbar_fontfamily        => :match,
    :colorbar_ticks              => :auto,
    :colorbar_tickfontfamily    => :match,
    :colorbar_tickfontsize      => 8,
    :colorbar_tickfontcolor     => :match,
    :colorbar_scale             => :identity,

isentropic avatar Mar 25 '21 02:03 isentropic

currently no c_*** aliases are made yet, but let's first make sure this works

isentropic avatar Mar 25 '21 02:03 isentropic

Thanks, I'll try to give some feedback in the next few days

rafaqz avatar Mar 25 '21 02:03 rafaqz

Naturally you'd need to use #master branch before we get a relase

isentropic avatar Mar 25 '21 02:03 isentropic

These work perfectly for me. Although I'm not sure what the allowed values for colorbar_scale are?

It would be good to add a few controls for the colorbar border too, like color/width etc. Seems it may be easy to copy your PR now to add some related args :)

rafaqz avatar Mar 28 '21 16:03 rafaqz

colorbar_scale takes :log10, :log2 and :identity (same as axis). Regarding the border and the color, it is strange that you want to change it even. Right now pyplot has 5% border width of the main plot, and I have no idea what do you wish we could've controlled the color

isentropic avatar Mar 29 '21 02:03 isentropic

Oh right yep scale works well too.

With color/width - there are situations where you don't want a border on the colorbar, or you want it to be less prominent. For example, if you use e.g. :border=:none the plot has no border, but the colorbar still has one, and it doesn't look great. You may also want to use e.g. a ligher grey border instead of black, or use a thinner border, to push the colorbar back and make the plot stand out more. That being said, the PyPlot colorbar does look alright as-is most of the time, GR less so.

But I can add this later.

rafaqz avatar Mar 29 '21 03:03 rafaqz

Thank you for working on this! colorbar_scale is working nicely; however now the problem is the color gradient itself. When the colorbar_scale is switched to :log10 the color gradient follows it likewise. Therefore, once colorbar_scale = :log10 is set only the colorbar changes, and not the actual colors on the heatmap. When I tried to manually fix this by using something like cgrad(:inferno, scale =:exp) I came across the bug reported on #3420. pyplot no longer respects a color gradient's scale

hervasa2 avatar Jun 09 '21 18:06 hervasa2

Right, I've been aware of this for a while. The attempt to fix was here #3432. I need some additional testers

isentropic avatar Jun 10 '21 03:06 isentropic

Right now this is a pyplot issue right? I just want to make sure that simplest behavior is still functional. Please let me know if

  1. Normal linear scale colorbars work as intended with pyplot
  2. Markers are not properly colored with the log scale colorbar.

isentropic avatar Jun 10 '21 03:06 isentropic

Thanks for your quick response! Yes this is a pyplot issue only.

  1. Normal linear scale colorbars work as intended with pyplot. Base functionality looks fine.
  2. Markers are not properly colored with the log scale colorbar. This applies both to the cases where one uses colorbar_scale = :log or when color = cgrad(:inferno, scale =:log)

In the meantime I will test #3432

hervasa2 avatar Jun 10 '21 09:06 hervasa2

I think the first order of business would be to get color = cgrad(:inferno, scale =:log) working again since this is something that was broken. Then I like the axis formatter approach suggested by @isentropic in #3432:

"Can't Plots just provide axis formatters? For example: I am plotting a 10^2, 10^3, 10^4 (three points) in log scale, Then, Plots would just log it to get -> (2, 3, 4) Then, just decorate the axis labels as (10^2, 10^3, 10^4) (instead of natural 2,3,4)"

hervasa2 avatar Jun 10 '21 09:06 hervasa2

I'm not sure how to handle colorbars with log scale right now. I don't think we should focus on (cgrad=:log) just yet. In the pr Cscale=log produces normal looking colorbar (color transition in the gradient looks uniform). However the markers are wrong color.

The problem is that I'm not so sure where Plots assigns marker colors to the points . If someone has an idea do let me know.

isentropic avatar Jun 10 '21 11:06 isentropic

Marker colors are stored in the marker_z seriesattribute, but maybe I got the question wrong

BeastyBlacksmith avatar Jun 10 '21 12:06 BeastyBlacksmith

Yes, I'm aware of that, but where does it get assigned? Somewhere in the depths of the pipeline but I could not find where

isentropic avatar Jun 10 '21 13:06 isentropic

Aren't those given from the callsite? Or do you have examples where there is automatic color assignment?

BeastyBlacksmith avatar Jun 10 '21 13:06 BeastyBlacksmith

In case of the colorbar, I think the colors need to be assigned somehow? Perhaps I'm missing something here but I thought marker color gets overriten when a colobar is present

isentropic avatar Jun 10 '21 14:06 isentropic

Its the other way around. You get a colorbar of you got marker_z values. How should Plots now what values to put there?

BeastyBlacksmith avatar Jun 10 '21 17:06 BeastyBlacksmith

@hervasa2 @rafaqz checkout the PR https://github.com/JuliaPlots/Plots.jl/pull/3620

isentropic avatar Jul 06 '21 06:07 isentropic

need testing and feedback from you

isentropic avatar Jul 06 '21 06:07 isentropic

Thanks for the work on this! Is there any progress especially on the log scale colorbar? What is stopping us from merging #3620?

henry2004y avatar Oct 24 '21 22:10 henry2004y

Lack of testing and user feedback

isentropic avatar Oct 25 '21 04:10 isentropic

That PR is outdated I believe, given a large demand I could revise it.

isentropic avatar Oct 25 '21 05:10 isentropic

Hmm, I don't know if I myself can be representative for a large demand... But for certain the lack of smooth support of log scale colormap/colorbar is one of the reasons I would still prefer matplotlib in production work. I don't feel urgent on this feature since we do have other alternatives, but it's good to have one and maybe I can help test the features and give feedbacks.

henry2004y avatar Oct 25 '21 06:10 henry2004y

The reason I'm hesitant to merge it is that the colors did not look right to me sometimes. Dangerous decision to plot something that is not representing the actual data. Need to test this thoroughly.

My personal workaround is just to log the data preemptively.

isentropic avatar Oct 25 '21 07:10 isentropic

I actually have a use case where taking the log on the data cannot work: a histogram2d with weights.

x = rand(1000)
y = rand(1000)
w = 10 .^(10 .* rand(1000))
histogram2d(x, y, nbins=20, weights = w)

In this case I really need a log scale colorbar.

henry2004y avatar Oct 25 '21 12:10 henry2004y

Lack of testing and user feedback

Sorry I thought I had already tested the new functionality and it was merged?

What was added with the second PR that was different to before? A description for the PR would help with feedback.

rafaqz avatar Oct 25 '21 14:10 rafaqz

The second PR actually fixes logscale colors

isentropic avatar Oct 26 '21 04:10 isentropic

First time the color reflected in the colorbar was not matching the data

isentropic avatar Oct 26 '21 04:10 isentropic

Other backend are still to support the colorbar_scale feature. For example, with PGFPlotsX: image

zhiyuanzhai avatar Apr 12 '22 05:04 zhiyuanzhai