Plotting multiple data sets as one average and adding error bars- matplotlib

1.2k Views Asked by At

I need to analyze some data taken in my lab but it goes beyond my limited programming skills. I have multiple sets of similar data and I need to take the average of all of these and plot that with error bars. The idea is to plot the area of an optical signal (which is recorded by a photomultiplier tube) versus the angle of the diffuser that emits the optical signal. To collect the data, the diffuser is rotated from -60 to 60 degrees and stops every 3 degrees for the photomultiplier tube (PMT) to record the area optical waveform. I have three individual sets of data that look like PMT = (angle, area). (Ignore the diode data. That is used to normalize the area values for the PMT so essentially what is plotted is PMT = (angle, normalizedarea.) )Instead of three individual graphs in one plot (like the picture attached has) I need to plot them all as one average of the three data sets combined and with error bars to show the deviation between data sets. Thank you in advance! Here is my code:

 from pathlib import Path
 import numpy as np
 import matplotlib.pyplot as plt 
 import matplotlib as mpl

 PMT1 = ([-60,-57,-54,-51,-48,-45,-42,-39,-36,-33,-30,-27,-24,-21,-18,-15,-12,-9,-6,-3,0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60],[6.751,7.115,7.40,7.646,7.839,8.101,8.319,8.452,8.843,8.954,9.202,9.270,9.521,9.612,9.632,9.740,9.928,9.991,10.06,10.11,10.13,10.07,9.998,10.08,9.952,9.847,9.668,9.413,9.465,9.322,9.017,8.815,8.716,8.385,8.257,8.093,7.880,7.623,7.477,7.379,6.968])

 diode1 = ([-60,-57,-54,-51,-48,-45,-42,-39,-36,-33,-30,-27,-24,-21,-18,-15,-12,-9,-6,-3,0,3,6,9,12,15,18,21 
,24,27,30,33,36,39,42,45,48,51,54,57,60],[0.01021,0.01016,0.01020,0.01011,0.01013,0.01019,0.01015,0.01020,0.01022,0.01027,0.01037,0.01024,0.010170,0.01028,0.01022,0.01032,0.01026,0.01028,0.01022,0.01026,0.01036,0.01033,0.01021,0.01036,0.01030,0.01012,0.01014,0.01024,0.01019,0.01020,0.01028,0.01035,0.01021,0.01023,0.01017,0.01017,0.01025,0.01026,0.01011,0.01017,0.01006])


 PMT2 = ([-60,-57,-54,-51,-48,-45,-42,-39,-36,-33,-30,-27,-24,-21,-18,-15,-12,-9,-6,-3,0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60],[7.012,7.157,7.420,7.587,7.867,8.070,8.271,8.473,8.836,9.114,9.228,9.392,9.462,9.592,9.688,9.798,9.945,9.892,10.03,9.869,10.19,10.06,9.928,9.988,9.850,9.753,9.601,9.589,9.459,9.302,9.078,8.960,8.744,8.596,8.415,8.096,8.002,7.757,7.498,7.276,6.973])

 diode2 = ([-60,-57,-54,-51,-48,-45,-42,-39,-36,-33,-30,-27,-24,-21,-18,-15,-12,-9,-6,-3,0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60],[0.009975,0.01014,0.01018,0.01016,0.01019,0.01010,0.01029,0.01029,0.01027,0.01028,0.01031,0.01016,0.01012,0.01038,0.01022,0.01037,0.01029,0.01020,0.01031,0.01041,0.01030,0.01031,0.01019,0.01031,0.01034,0.01027,0.01033,0.01037,0.01024,0.01026,0.01032,0.01035,0.01034,0.01022,0.01025,0.01007,0.01004,0.01024,0.01012,0.01023,0.01014])

 PMT4 = ([-60,-57,-54,-51,-48,-45,-42,-39,-36,-33,-30,-27,-24,-21,-18,-15,-12,-9,-6,-3,0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60],[7.043,7.222,7.462,7.746,7.974,8.181,8.285,8.542,8.731,8.824,8.994,9.103,9.258,9.473,9.579,9.792,9.797,9.999,10.03,10,9.914,9.943,9.914,9.884,9.7813,9.676,9.502,9.440,9.245,9.272,9.091,8.858,8.761,8.397,8.225,8.007,7.862,7.725,7.367,7.149,6.938])

 diode4 = ([-60,-57,-54,-51,-48,-45,-42,-39,-36,-33,-30,-27,-24,-21,-18,-15,-12,-9,-6,-3,0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60],[0.01001,0.01001,0.01005,0.01017,0.01002,0.01003,0.009996,0.01015,0.01005,0.01021,0.01014,0.01016,0.01019,0.01014,0.01022,0.01021,0.01018,0.01015,0.01022,0.01030,0.01003,0.01015,0.01010,0.01022,0.01020,0.01021,0.01018,0.01006,0.01012,0.01006,0.01007,0.01012,0.01008,0.01003,0.01010,0.01012,0.01006,0.01009,0.01001,0.01004,0.009927])



 angle1 = np.array(PMT1[0])
 area1 = np.array(PMT1[1])
 p1 = np.array(diode1[1])
 plt.plot(angle1,area1*np.mean(p1)/p1)

 angle2 = np.array(PMT2[0])
 area2 = np.array(PMT2[1])
 p2 = np.array(diode2[1])
 plt.plot(angle2,area2*np.mean(p2)/p2)

 angle4 = np.array(PMT4[0])
 area4 = np.array(PMT4[1])
 p4 = np.array(diode4[1])
 plt.plot(angle4,area4*np.mean(p4)/p4)


 plt.show()

Image

1

There are 1 best solutions below

0
On

You could do the necessary calculations in NumPy and then plot the results.

To do this efficiently, I would first combine all the area values into one two-dimensional array with np.vstack. Then you can calculate the means etc. between the various measurement series by calling the appropriate NumPy methods on that array with axis=0.

The angle values are the same for all three series, so we can just use angle1 throughout.

"Error bars" is an ambiguous term, so you will have to decide what the bars should represent. In the code below, I chose to show +/- one sample standard deviation. In any case, you can use plt.fill_between to plot the series of these values as error bands.

assert (angle1 == angle2).all()
assert (angle1 == angle4).all()

area1_norm = area1 * np.mean(p1) / p1
area2_norm = area2 * np.mean(p2) / p2
area4_norm = area4 * np.mean(p4) / p4

areas = np.vstack([area1_norm, area2_norm, area4_norm])
means = areas.mean(axis=0)
stds = areas.std(axis=0, ddof=1)

plt.plot(angle1, means)
plt.fill_between(angle1, means - stds, means + stds, alpha=0.3)
plt.show()

Resulting plot