Search code examples
pythonmatplotlibbar-charthistogramcolor-coding

Vertical "broken" bar plot with arrays as bar heights and color coding


I am trying to create a bar plot that looks like this:

1

x axis is the number of detectors hit in coincidence (i.e. multiplicity) for each multiplicity i have several events. The y axis contains the average pulse height of each event.The colors should correspond to the number of hits which have the shown pulse heights and appeared in events with the respective multiplicity

I have a dictionary that has multiplicities as keys and arrays of the avarage pulse heights as values. :

averages = {2 : [...],
        3 : [...],
        4 : [...],
        5 : [...],
        6 : [...],}

for key in averages:
plt.bar(key,averages[key] ,width = 0.8)

i only know how to produce the simple version of a bar chart that looks like this:

2

can someone tell me how to make the bars "broken to show all pulse heights and add the color coding?


Solution

  • Here is a solution which uses imshow to produce the columnwise "color histograms":

    import matplotlib as mpl
    import matplotlib.pyplot as plt
    import numpy as np
    
    # Create dummy data
    coincidences = [2, 3, 4, 5, 6]
    n_list = [10000, 8000, 6000, 4000, 2000]
    mu_list = np.array([200, 300, 400, 500, 600])
    scale = 100
    averages = {c: np.random.normal(loc=mu_list[i], scale=scale, size=n_list[i])
                for i, c in enumerate(coincidences)}
    
    # Calculate histogram for each column
    bins = np.linspace(0, 1000, 1000)
    hist_img = np.array([np.histogram(averages[c], bins=bins)[0]
                         for c in coincidences]).T
    
    # Create Normalized colormap
    # norm = mpl.colors.Normalize()
    norm = mpl.colors.LogNorm(vmin=1, vmax=hist_img.max())
    sm = mpl.cm.ScalarMappable(cmap='viridis', norm=norm)
    
    # Use colormap for img_hist and make zeros transparent
    hist_img2 = sm.to_rgba(hist_img, bytes=True)
    hist_img2[hist_img == 0, 3] = 0
    
    # Plot
    fig, ax = plt.subplots()
    cc = ax.imshow(hist_img2, aspect='auto', interpolation='none', origin='lower',
                   extent=[1.5, 6.5, 0, 1000])
    plt.colorbar(sm)
    
    mean = [np.mean(averages[c]) for c in coincidences]
    std = [np.std(averages[c]) for c in coincidences]
    ax.errorbar(coincidences, mean, yerr=std, ls='', c='k', capsize=3, label='std')
    ax.plot(coincidences, mean, ls='', marker='o', c='b', label='mean')
    ax.legend()
    

    enter image description here