jiffyclub / palettable

Color palettes for Python
https://jiffyclub.github.io/palettable/
Other
768 stars 73 forks source link

Cubehelix #13

Closed jonathansick closed 9 years ago

jonathansick commented 9 years ago

This PR implements cubehelix color maps in palettable by porting @jradavenport's cubehelix.py. I put a demo notebook up as a gist here. I think it's sweet.

I've kept the API for palettable.cubehelix as similar as possible to the other palettes. Basically, the Cubehelix(Palette) class computes colors for the color map. get_map() is a factory that takes pre-defined parameter sets and creates Cubehelix instances. The user is also encouraged to build their own maps directly.

I've spruced up the cubehelix algorithm implementation a bit. Some parameters are renamed for clarity. I also use numpy.dot() to build the entire RGB color vector in one statement. Anyways, it's a bit more Pythonic and a little less... Fortranic?

I also noticed a discrepancy between D.A. Green's formula for phi and the Fortran code (and the original Python implementation); there's an issue of adding an extra +1. I've stayed true to the formula in the paper, although I don't actually notice any difference in the outputs.

Some issues I see:

Let me know what you think!

coveralls commented 9 years ago

Coverage Status

Coverage decreased (-0.99%) to 91.29% when pulling 84d274486712470fb10c4cad39514faeb94bff4c on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

coveralls commented 9 years ago

Coverage Status

Coverage decreased (-0.99%) to 91.29% when pulling b567b5dc5919559244e8c6dc9b92aa622b2e7546 on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

coveralls commented 9 years ago

Coverage Status

Coverage decreased (-0.99%) to 91.29% when pulling b567b5dc5919559244e8c6dc9b92aa622b2e7546 on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

jonathansick commented 9 years ago

@jiffyclub Looks like there are two test issues here:

jiffyclub commented 9 years ago

You can see in palette.py how I'm protecting matplotlib imports. There's enough numpy usage in there that I don't necessarily want to make you replace it all with pure python. What if the data for all the default palettes was pre-computed and stored in the file so that people only needed numpy when creating custom versions of cubehelix? It looks like the default palettes are defined by 256 RGB points, which is probably more than strictly necessary. matplotlib does linear interpolation between the points you give it, so if you generated even 16 RGB points for the default palettes I bet they'd look decent (though that'd require some testing).

jiffyclub commented 9 years ago

I can take care of adding a doc page before the next release, but do feel free to add a notebook to the demo/ directory.

The colors as 2D array thing works because ndarrays are sufficiently list like when you iterate over them. You get a 1D row of length three on each iteration, which is what the code is expecting. All the looping looks like for color in self.colors.

We'll need to fix the hex colors coming out the the L's, that's not right. There must be long integers:

In [6]: '{:>02}'.format(hex(128L)[2:].upper())
Out[6]: '80L'

We can fix that by coercing to int before converting to hex here.

jiffyclub commented 9 years ago

Here's an example of how you don't need a large number of RGB points to make these palettes:

screen shot 2015-04-28 at 10 42 49 am

So I think we could pre-generate the default cubehelix palettes and store the numbers in there so folks can access them with a pure Python install of palettable. Maybe add a class method or something for creating a Cubehelix instance from pre-generated numbers?

jonathansick commented 9 years ago

Yeah! I'll push something soon with the class method and pre-baked RGB lists. I'm just at a meeting right now at github of all places.

coveralls commented 9 years ago

Coverage Status

Coverage decreased (-1.24%) to 91.03% when pulling b79fdc11a3dc3cd7673aab0b209b911bf338e1df on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

coveralls commented 9 years ago

Coverage Status

Coverage decreased (-1.24%) to 91.03% when pulling b79fdc11a3dc3cd7673aab0b209b911bf338e1df on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

coveralls commented 9 years ago

Coverage Status

Coverage decreased (-1.18%) to 91.1% when pulling f695437c36fb8fe034df6cebbc2720dbd166519d on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

coveralls commented 9 years ago

Coverage Status

Coverage decreased (-1.18%) to 91.1% when pulling f9b2e56bc8cc5f740131385bc20187f6b603ef46 on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

jiffyclub commented 9 years ago

Looks great! I saw you went with a class method for making the custom palettes. That was the only way I could think to make it work as well. An alternative solution would be to keep the Cubehelix class as you had it originally but have the default ones be Palette instances instead. But then they aren't Cubehelix instances. I'm happy with the Cubehelix.make class method if you are.

jonathansick commented 9 years ago

I think the class method makes total sense. Better to keep the API uniform and be explicit about generating the palette rather than using one

Do you have any stylistic requests? I'll fix the test coverage gaps.

jiffyclub commented 9 years ago

Looks great! Such PEP8, very wow. :smile_cat:

I think the last thing to make sure of is that we aren't ending up with L's in the hex color strings.

coveralls commented 9 years ago

Coverage Status

Coverage decreased (-12.34%) to 79.93% when pulling 542a165c95fb39a5e58654e800379ddd738dc032 on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

jonathansick commented 9 years ago

I think I've resolved the last few details:

jiffyclub commented 9 years ago

One thing I just remembered is that I've started putting the number of defined colors at the end of the palette names. So e.g. in the tableau module there are palettes named like BlueRed_6 and BlueRed_12. Here those would all be _16, but for consistency I think it should be there. I put that suffix there so people accessing the palettes via tab completion can quickly tell how many defined colors there are.

coveralls commented 9 years ago

Coverage Status

Coverage increased (+1.22%) to 93.49% when pulling 889bd1a3d866eab8eccfe6e70d2eeccaa902efb7 on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

coveralls commented 9 years ago

Coverage Status

Coverage increased (+1.56%) to 93.84% when pulling 952d798bba9f162cab4e62bb2f6725931543350d on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

coveralls commented 9 years ago

Coverage Status

Coverage increased (+1.56%) to 93.84% when pulling 6e0b83c13f5e5b48117fb4fa9652092cd506cd75 on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

jiffyclub commented 9 years ago

Looking good! Ready to go?

jonathansick commented 9 years ago

@jiffyclub I think so! Do you want me to squash everything into one commit?

Also, I was trying to make the docs with cubehelix but urubu was getting links wrong (even to the existing sub pages). So maybe I'll leave docs off of this PR after all.

jiffyclub commented 9 years ago

Urubu can make it hard to preview things locally because they have to served from a http://host/palettable/ URL. I had to make the tservice tool specifically for previewing these docs locally, e.g. with tserve --prefix palettable _build.

I don't care one way or the other about squashing commits. If you want to do any cleanup go for it, but I'm happy to merge whenever.

jonathansick commented 9 years ago

Okay, give me a sec and I'll see if I can ship some docs with it.

coveralls commented 9 years ago

Coverage Status

Coverage increased (+1.56%) to 93.84% when pulling 493a2907e8bc79e944572ac6144cdb23c2dcf214 on jonathansick:cubehelix into 7a2864ebf2719933c13ca2532b2160e10e3a1bb7 on jiffyclub:master.

jonathansick commented 9 years ago

I've put together a doc page for cubehelix. It includes both previews and an API reference section for making palettes. I don't entirely like just listing the arguments the way I did, but it works. Maybe laying out the API via a table would be better.

:shipit:?

jiffyclub commented 9 years ago

A table would work, but I don't want to muck around with a table in Markdown. Honestly I was just going to put in the raw output of print(Cubehelix.__doc__), so :+1:. Merging!

jonathansick commented 9 years ago

Thanks for your help with this!

jiffyclub commented 9 years ago

Thank you!