У меня есть несколько вопросов о настройке гистограммы в python с помощью matplotlib.
# Start or E fitting <<<<<<<<<
plt.figure(1)
n, bins, patches = plt.hist(array_E, bins=1400, range=(0.0,1.400), label = "Energy", color = "blue")
# We know that the mean should be 0.511, so we select the region around the peak...
mass_emin = 0.511
delta = 0.008 # 0.010
peak_E = []
for E in array_E:
if ( (E > mass_emin - delta) and (E < mass_emin + delta) ):
peak_E.append(E)
plt.hist(peak_E, bins=1400, range=(0.0,1.400), label = "Energy peak", color = "red")
mu, sigma = scipy.stats.norm.fit(peak_E)
print("fit results: ", mu, sigma)
best_fit_line = scipy.stats.norm.pdf(bins, mu, sigma)
plt.plot(bins, best_fit_line, color = "green")
plt.show(block=False)






scipy.stats.norm.pdf является функцией плотности вероятности, и поэтому ее площадь равна 1. Чтобы нарисовать его того же размера, что и красные полосы, вы можете рассчитать площадь этих полос (сумма их высот, умноженных на ширину). А затем умножьте PDF на эту область:
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats
# first create some toy data, somewhat similar to the example plot
array_E = np.random.randn(100, 1000).cumsum(axis=1).ravel() * 0.0005 + 0.511
plt.figure(1)
_, bins, _ = plt.hist(array_E, bins=1400, range=(0.0, 1.400), label = "Energy", color = "blue")
mass_emin = 0.511
delta = 0.008
peak_E = array_E[np.abs(array_E - mass_emin) < delta]
n, _, _ = plt.hist(peak_E, bins=1400, range=(0.0, 1.400), label = "Energy peak", color = "red")
bin_width = bins[1] - bins[0]
area = np.sum(n) * bin_width
mu, sigma = scipy.stats.norm.fit(peak_E)
print("fit results: ", mu, sigma)
best_fit_line = scipy.stats.norm.pdf(bins, mu, sigma) * area
plt.plot(bins, best_fit_line, color = "green")
plt.xlim(mass_emin - 3 * delta, mass_emin + 3 * delta) # zoom into the region on the x-axis
plt.show()
PS: Следующий код вычисляет меру ошибки:
bin_mids = (bins[:-1] + bins[1:]) / 2
squared_error = ((scipy.stats.norm.pdf(bin_mids, mu, sigma) * area - n) ** 2).sum()
print("squared_error div degrees_of_freedom: ", squared_error / (n.size - 3))
Ну, каждое программное обеспечение имеет свои определенные функции. В этом случае площадь довольно просто вычислить. Поскольку площадь зависит от ширины бина, подгонка может быть рассчитана только с учетом гистограммы, а не как отдельная функция numpy с только выборками в качестве входных данных. Вы можете увидеть изменения по оси Y после изменения параметра bins=.
Хорошо, я думаю, мне придется привыкнуть к этому, когда я захочу использовать python. Есть ли способ получить хи-квадрат из фита? Потому что подгонка бесполезна, если не знать ее качества.
Спасибо за ваш ответ. Я попробую это, но я немного удивлен, насколько сложным, по-видимому, является этот примерный бизнес в Python. Я привык к программе CERN ROOT (на основе C++), и с помощью этого программного обеспечения можно: 1) выбрать область гистограммы для подгонки и 2) напрямую подогнать гауссиану поверх данных без необходимости умножать что-либо. Разве в python нет библиотеки, которая это делает? Я попробовал Numpy, но не смог найти то, что искал.