Reading-eScience-Centre / edal-java

Environmental Data Abstraction Layer libraries
Other
39 stars 30 forks source link

Adding more colormaps #40

Closed PBrockmann closed 8 years ago

PBrockmann commented 8 years ago

Many colormaps have already been made available from ncWMS especially ones from matplotlib and is a very nice thing. I would like to add some more. Especially some Perceptually Uniform Sequential colormaps (viridis, magma, inferno, and plasma) that matplolib has delivered from their last release.

See http://matplotlib.org/examples/color/colormaps_reference.html and https://youtu.be/xAoljeRJ3lU - A Better Default Colormap for Matplotlib

So does ncWMS palette files accept 256 colors ? The documentation does not specify this limitation I suspect existing.

Is the HTML color notation (#RRGGBB or #AARRGGBB) the only accepted format to specify color palette ? Would be nice to allow rbg values in a flat tsv or csv file as well (https://github.com/BIDS/colormap/blob/master/option_d.py)

guygriffiths commented 8 years ago

That would be great - if you create some palette files I'd be happy to incorporate them.

Currently the accepted formats for colours are:

RRGGBB

AARRGGBB

0xRRGGBB 0xAARRGGBB any of the names listed in https://raw.githubusercontent.com/Reading-eScience-Centre/edal-java/develop/graphics/src/main/resources/colors.csv

A palette consists of a string of these colours separated by either a comma, a colon, or a newline character.

ncWMS palettes accept between 2 and 250 colours inclusive (we kept some reserved from the 256 for black, white, transparent etc for cases where we want an indexed palette)

PBrockmann commented 8 years ago

No problem. I can send them to you or perhaps better idea the 10 lines of python that produce them. How many colors are needed ? The maximum ie 250 ? Do you need reversed palette as well ?

PBrockmann commented 8 years ago

Here is a script set to produce palette files with 50 colors. matplotlib 1.5.0 is needed to get described colormaps. You get 142 palette files. A little too much. Interesting ones are the Perceptually Uniform Sequential ones so starting by mpl_PSU

############################
#!/usr/bin/env python

import numpy as np
import matplotlib.pyplot as plt
import matplotlib

# Have colormaps separated into categories:
# http://matplotlib.org/examples/color/colormaps_reference.html

cmaps = [('PSU',  # Perceptually Uniform Sequential'
                            ['viridis', 'inferno', 'plasma', 'magma']),
         ('Seq1', # Sequential
                            ['Blues', 'BuGn', 'BuPu',
                             'GnBu', 'Greens', 'Greys', 'Oranges', 'OrRd',
                             'PuBu', 'PuBuGn', 'PuRd', 'Purples', 'RdPu',
                             'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd',
                             'afmhot', 'autumn', 'bone', 'cool',
                             'copper', 'gist_heat', 'gray', 'hot',
                             'pink', 'spring', 'summer', 'winter']),
         ('Div',  # Diverging
                             ['BrBG', 'bwr', 'coolwarm', 'PiYG', 'PRGn', 'PuOr',
                             'RdBu', 'RdGy', 'RdYlBu', 'RdYlGn', 'Spectral',
                             'seismic']),
         ('Qual', # Qualitative   
                             ['Accent', 'Dark2', 'Paired', 'Pastel1',
                             'Pastel2', 'Set1', 'Set2', 'Set3']),
         ('Misc', # Miscellaneous 
                             ['gist_earth', 'terrain', 'ocean', 'gist_stern',
                             'brg', 'CMRmap', 'cubehelix',
                             'gnuplot', 'gnuplot2', 'gist_ncar',
                             'nipy_spectral', 'jet', 'rainbow',
                             'gist_rainbow', 'hsv', 'flag', 'prism'])]

levels = 50

for cmap_category, cmap_list in cmaps:
    for cmap_name in cmap_list:
        print cmap_category+'_'+cmap_name

        file = open('mpl_' + cmap_category + "_" + cmap_name + ".pal", "w")

        cmap = plt.get_cmap(cmap_name)
        colors = cmap(np.linspace(0, 1, levels))

        for i,c in enumerate(colors):
                c = matplotlib.colors.rgb2hex(c)
                file.write("%s\n" %(c))

        file.close()
guygriffiths commented 8 years ago

Thanks, I will try and have a look at those in the near future. 142 is definitely too many palettes (it would require a rethink of the UI for a start...), are there any you're particularly keen on?

The ideal number of colours is the minimum number which define the palette - i.e. for divergent palettes it is probably 3 colours, whereas for some of the perceptually linear ones 250 might be better. Colours in between are interpolated linearly on their RGB values. Adding "-rev" to a palette name already reverses the palette on-the-fly in ncWMS2

PBrockmann commented 8 years ago

Interesting ones are the Perceptually Uniform Sequential ones so starting by mpl_PSU in my code. So 'viridis', 'inferno', 'plasma', 'magma'.

I have lightly modify the code above to remove reverse writing since it is done on the fly by ncWMS. I left also 50 colors because if you set 250 you get sometimes colors with similar HTML codes.

[ 0.126453  0.570633  0.549841  1.      ] ----> #20928c
[ 0.125394  0.574318  0.549086  1.      ] ----> #20928c
guygriffiths commented 8 years ago

OK, for the time being I'll just add those 4 palettes. Could you either send them to me or do a fork/pull request to the develop branch? I don't have access to a new enough version of matplotlib at the moment.

PBrockmann commented 8 years ago

Ok, I made a PR.