Colormap with maximum distinguishable colours

后端 未结 2 431
野性不改
野性不改 2021-02-05 15:49

Using matplotlib in Python I\'m plotting anywhere between 20 and 50 lines. Using matplotlib\'s sliding colour scales these become indistinguishable after a certain number of li

2条回答
  •  孤城傲影
    2021-02-05 16:14

    I loved the idea of palette created by @xuancong84 and modified his code a bit to make it not depending on alpha channel. I drop it here for others to use, thank you @xuancong84!

    import math
    
    import numpy as np
    from matplotlib.colors import ListedColormap
    from matplotlib.cm import hsv
    
    
    def generate_colormap(number_of_distinct_colors: int = 80):
        if number_of_distinct_colors == 0:
            number_of_distinct_colors = 80
    
        number_of_shades = 7
        number_of_distinct_colors_with_multiply_of_shades = int(math.ceil(number_of_distinct_colors / number_of_shades) * number_of_shades)
    
        # Create an array with uniformly drawn floats taken from <0, 1) partition
        linearly_distributed_nums = np.arange(number_of_distinct_colors_with_multiply_of_shades) / number_of_distinct_colors_with_multiply_of_shades
    
        # We are going to reorganise monotonically growing numbers in such way that there will be single array with saw-like pattern
        #     but each saw tooth is slightly higher than the one before
        # First divide linearly_distributed_nums into number_of_shades sub-arrays containing linearly distributed numbers
        arr_by_shade_rows = linearly_distributed_nums.reshape(number_of_shades, number_of_distinct_colors_with_multiply_of_shades // number_of_shades)
    
        # Transpose the above matrix (columns become rows) - as a result each row contains saw tooth with values slightly higher than row above
        arr_by_shade_columns = arr_by_shade_rows.T
    
        # Keep number of saw teeth for later
        number_of_partitions = arr_by_shade_columns.shape[0]
    
        # Flatten the above matrix - join each row into single array
        nums_distributed_like_rising_saw = arr_by_shade_columns.reshape(-1)
    
        # HSV colour map is cyclic (https://matplotlib.org/tutorials/colors/colormaps.html#cyclic), we'll use this property
        initial_cm = hsv(nums_distributed_like_rising_saw)
    
        lower_partitions_half = number_of_partitions // 2
        upper_partitions_half = number_of_partitions - lower_partitions_half
    
        # Modify lower half in such way that colours towards beginning of partition are darker
        # First colours are affected more, colours closer to the middle are affected less
        lower_half = lower_partitions_half * number_of_shades
        for i in range(3):
            initial_cm[0:lower_half, i] *= np.arange(0.2, 1, 0.8/lower_half)
    
        # Modify second half in such way that colours towards end of partition are less intense and brighter
        # Colours closer to the middle are affected less, colours closer to the end are affected more
        for i in range(3):
            for j in range(upper_partitions_half):
                modifier = np.ones(number_of_shades) - initial_cm[lower_half + j * number_of_shades: lower_half + (j + 1) * number_of_shades, i]
                modifier = j * modifier / upper_partitions_half
                initial_cm[lower_half + j * number_of_shades: lower_half + (j + 1) * number_of_shades, i] += modifier
    
        return ListedColormap(initial_cm)
    
    

    These are the colours I get:

    from matplotlib import pyplot as plt
    import numpy as np
    
    N = 16
    M = 7
    H = np.arange(N*M).reshape([N,M])
    fig = plt.figure(figsize=(10, 10))
    ax = plt.pcolor(H, cmap=generate_colormap(N*M))
    plt.show()
    

提交回复
热议问题