code base 5000
code base 5000

Reputation: 4112

Scaling plot sizes with Matplotlib

I have taken the display colormap code and made it more generic. The problem is that the color maps are now all smooshed together so the graphics are basically unreadable.

How do I increase the size of each colormap display?

Current output:

current result

import numpy as np
import matplotlib.pyplot as plt


# Have colormaps separated into categories:
# http://matplotlib.org/examples/color/colormaps_reference.html
cmaps =  [('All Color Maps',
"Accent, Accent_r, Blues, Blues_r, BrBG, BrBG_r, BuGn, BuGn_r, BuPu, BuPu_r, CMRmap, CMRmap_r, Dark2, Dark2_r, GnBu, GnBu_r, Greens, Greens_r, Greys, Greys_r, OrRd, OrRd_r, Oranges, Oranges_r, PRGn, PRGn_r, Paired, Paired_r, Pastel1, Pastel1_r, Pastel2, Pastel2_r, PiYG, PiYG_r, PuBu, PuBuGn, PuBuGn_r, PuBu_r, PuOr, PuOr_r, PuRd, PuRd_r, Purples, Purples_r, RdBu, RdBu_r, RdGy, RdGy_r, RdPu, RdPu_r, RdYlBu, RdYlBu_r, RdYlGn, RdYlGn_r, Reds, Reds_r, Set1, Set1_r, Set2, Set2_r, Set3, Set3_r, Spectral, Spectral_r, Wistia, Wistia_r, YlGn, YlGnBu, YlGnBu_r, YlGn_r, YlOrBr, YlOrBr_r, YlOrRd, YlOrRd_r, afmhot, afmhot_r, autumn, autumn_r, binary, binary_r, bone, bone_r, brg, brg_r, bwr, bwr_r, cool, cool_r, coolwarm, coolwarm_r, copper, copper_r, cubehelix, cubehelix_r, flag, flag_r, gist_earth, gist_earth_r, gist_gray, gist_gray_r, gist_heat, gist_heat_r, gist_ncar, gist_ncar_r, gist_rainbow, gist_rainbow_r, gist_stern, gist_stern_r, gist_yarg, gist_yarg_r, gnuplot, gnuplot2, gnuplot2_r, gnuplot_r, gray, gray_r, hot, hot_r, hsv, hsv_r, inferno, inferno_r, jet, jet_r, magma, magma_r, nipy_spectral, nipy_spectral_r, ocean, ocean_r, pink, pink_r, plasma, plasma_r, prism, prism_r, rainbow, rainbow_r, seismic, seismic_r, spectral, spectral_r, spring, spring_r, summer, summer_r, terrain, terrain_r, viridis, viridis_r, winter, winter_r".replace(" ", "").split(',')
          )]
nrows = max(len(cmap_list) for cmap_category, cmap_list in cmaps)
gradient = np.linspace(0, 1, 256)
gradient = np.vstack((gradient, gradient))


def plot_color_gradients(cmap_category, cmap_list, nrows):
    fig, axes = plt.subplots(nrows=nrows)
    fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99)
    axes[0].set_title(cmap_category + ' colormaps', fontsize=14)

    for ax, name in zip(axes, cmap_list):
        ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(name))
        pos = list(ax.get_position().bounds)
        x_text = pos[0] - 0.01
        y_text = pos[1] + pos[3]/2.
        fig.text(x_text, y_text, name, va='center', ha='right', fontsize=10)

    # Turn off *all* ticks & spines, not just the ones with colormaps.
    for ax in axes:
        ax.set_axis_off()


for cmap_category, cmap_list in cmaps:

    plot_color_gradients(cmap_category, cmap_list, nrows)

plt.show()

Upvotes: 0

Views: 2518

Answers (2)

DavidG
DavidG

Reputation: 25380

If you insist on having the plot look as close to what you have shown as possible, i.e. one column of 256 subplots with large labels, then the only real solution is to increase the size of the figure as mentioned in the answer by @Diziet Asahi.

That being said, I have 2 proposals for improvement.

Option 1

Split the subplots into 2 columns. This makes the image far easier to read IMO. This only takes a small modification to your plotting function:

def plot_color_gradients(cmap_category, cmap_list, nrows):
    fig, axes = plt.subplots(nrows=int(nrows/2), ncols=2, figsize=(12,11))
    fig.subplots_adjust(top=0.95, bottom=0.01, left=0.1, right=0.98, wspace=0.25)
    fig.suptitle(cmap_category + ' colormaps', fontsize=14)

    for ax, name in zip(axes.flatten(), cmap_list):
        ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(name))
        pos = list(ax.get_position().bounds)
        x_text = pos[0] - 0.01
        y_text = pos[1] + pos[3]/2.
        fig.text(x_text, y_text, name, va='center', ha='right', fontsize=10)
        ax.set_axis_off() # Don't need a separate loop for this

Which gives:

enter image description here

Option 2

If you want to keep everything in 1 column there may be a work around to at least make the plot look slightly better. That is to put every other label on the right hand side of the axis.

Note: this may not be what be exactly what you are looking for, but unless you make the figure very large (tall) then the image is always going to look cramped

Changing your plotting function like so gives the following graph:

def plot_color_gradients(cmap_category, cmap_list, nrows):
    fig, axes = plt.subplots(nrows=nrows)
    fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.9)
    axes[0].set_title(cmap_category + ' colormaps', fontsize=14)

    count = 0
    for ax, name in zip(axes, cmap_list):
        ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(name))
        pos = list(ax.get_position().bounds)
        ax.set_axis_off()

        if count == 1:
            count = 0
            x_text = pos[0] + 0.71
            y_text = pos[1] + pos[3] / 2.
            fig.text(x_text, y_text, name, va='center', ha='left', fontsize=10)
        else:
            count = 1
            x_text = pos[0] - 0.01
            y_text = pos[1] + pos[3]/2.
            fig.text(x_text, y_text, name, va='center', ha='right', fontsize=10)

    # Theres no need to loop through list of axes twice. Do this in the above loop!

    # Turn off *all* ticks & spines, not just the ones with colormaps.
    #for ax in axes:
    #    ax.set_axis_off()

enter image description here

Not as good as the first example, but an improvement nonetheless.

Upvotes: 3

Diziet Asahi
Diziet Asahi

Reputation: 40747

As @DavidG commented, you need to increase the size of your figure. In the code below, replace width and height by appropriate values. Since you seem to want a variable number of lines, height should probably be proportional to nrows

def plot_color_gradients(cmap_category, cmap_list, nrows):
    height = some_value * nrows
    fig, axes = plt.subplots(nrows=nrows, figsize=(width, height))
    ...

Upvotes: 1

Related Questions