Search code examples
pythonmatplotlibscatter-ploterrorbar

Scatter plot with errorbars and colors mapping a physical quantity


I'm trying to do a quite simple scatter plot with error bars and semilogy scale. What is a little bit different from tutorials I have found is that the color of the scatterplot should trace a different quantity. On one hand, I was able to do a scatterplot with the errorbars with my data, but just with one color. On the other hand, I realized a scatterplot with the right colors, but without the errorbars. I'm not able to combine the two different things.

Here an example using fake data:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt

n=100
Lx_gas = 1e40*np.random.random(n) + 1e37
Tx_gas = np.random.random(n) + 0.5
Lx_plus_error = Lx_gas
Tx_plus_error = Tx_gas/2.
Tx_minus_error = Tx_gas/4.

#actually positive numbers, this is the quantity that should be traced by the
#color, in this example I use random numbers
Lambda = np.random.random(n) 

#this is actually different from zero, but I want to be sure that this simple
#code works with the log axis
Lx_minus_error = np.zeros_like(Lx_gas)

#normalize the color, to be between 0 and 1
colors = np.asarray(Lambda)
colors -= colors.min()
colors *=  (1./colors.max())

#build the error arrays
Lx_error = [Lx_minus_error, Lx_plus_error]
Tx_error = [Tx_minus_error, Tx_plus_error]

##--------------
##important part of the script

##this works, but all the dots are of the same color
#plt.errorbar(Tx_gas, Lx_gas, xerr = Tx_error,yerr = Lx_error,fmt='o')

##this is what is should be in terms of colors, but it is without the error bars
#plt.scatter(Tx_gas, Lx_gas, marker='s', c=colors)


##what I tried (and failed)
plt.errorbar(Tx_gas, Lx_gas, xerr = Tx_error,yerr = Lx_error,\
        color=colors,  fmt='o')


ax = plt.gca()
ax.set_yscale('log')
plt.show()

I even tried to plot the scatterplot after the errorbar, but for some reason everything plotted on the same window is put in background with respect to the errorplot. Any ideas?

Thanks!


Solution

  • You can set the color to the LineCollection object returned by the errorbar as described here.

    from __future__ import division
    import numpy as np
    import matplotlib.pyplot as plt
    
    n=100
    Lx_gas = 1e40*np.random.random(n) + 1e37
    Tx_gas = np.random.random(n) + 0.5
    Lx_plus_error = Lx_gas
    Tx_plus_error = Tx_gas/2.
    Tx_minus_error = Tx_gas/4.
    
    #actually positive numbers, this is the quantity that should be traced by the
    #color, in this example I use random numbers
    Lambda = np.random.random(n) 
    
    #this is actually different from zero, but I want to be sure that this simple
    #code works with the log axis
    Lx_minus_error = np.zeros_like(Lx_gas)
    
    #normalize the color, to be between 0 and 1
    colors = np.asarray(Lambda)
    colors -= colors.min()
    colors *=  (1./colors.max())
    
    #build the error arrays
    Lx_error = [Lx_minus_error, Lx_plus_error]
    Tx_error = [Tx_minus_error, Tx_plus_error]
    
    
    sct = plt.scatter(Tx_gas, Lx_gas, marker='s', c=colors)
    cb = plt.colorbar(sct)
    
    _, __ , errorlinecollection = plt.errorbar(Tx_gas, Lx_gas, xerr = Tx_error,yerr = Lx_error, marker = '', ls = '', zorder = 0)
    error_color = sct.to_rgba(colors)
    
    errorlinecollection[0].set_color(error_color)
    errorlinecollection[1].set_color(error_color)
    
    ax = plt.gca()
    ax.set_yscale('log')
    plt.show()
    

    enter image description here