Подгонка гистограммы matplotlib дает плохой результат (и только 2 параметра)

У меня есть несколько вопросов о настройке гистограммы в python с помощью matplotlib.

  1. Моя гистограмма представляет собой спектр, поэтому я не могу просто подобрать всю гистограмму, мне нужно выбрать область, в которой я хочу выполнить подбор. Мой код ниже создает специальную область для установки, но мне интересно, есть ли менее неуклюжий способ сделать это
  2. По какой-то причине «scipy.stats.norm.fit» возвращает только мю и сигму, тогда как подгонка по Гауссу, очевидно, имеет 3 параметра: среднее, сигма и амплитуда. Итак, как мне получить амплитуду подгонки?
  3. На прикрепленном изображении видно, что подгонка (зеленая линия) не очень хорошая. Среднее значение и сигма в порядке, но амплитуда недостаточно высока. Данные выглядят достаточно гауссовыми для гораздо лучшего соответствия, так как я могу это улучшить?
# 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)

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
271
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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))

Спасибо за ваш ответ. Я попробую это, но я немного удивлен, насколько сложным, по-видимому, является этот примерный бизнес в Python. Я привык к программе CERN ROOT (на основе C++), и с помощью этого программного обеспечения можно: 1) выбрать область гистограммы для подгонки и 2) напрямую подогнать гауссиану поверх данных без необходимости умножать что-либо. Разве в python нет библиотеки, которая это делает? Я попробовал Numpy, но не смог найти то, что искал.

Machiel Kolstein 13.12.2020 19:51

Ну, каждое программное обеспечение имеет свои определенные функции. В этом случае площадь довольно просто вычислить. Поскольку площадь зависит от ширины бина, подгонка может быть рассчитана только с учетом гистограммы, а не как отдельная функция numpy с только выборками в качестве входных данных. Вы можете увидеть изменения по оси Y после изменения параметра bins=.

JohanC 13.12.2020 23:01

Хорошо, я думаю, мне придется привыкнуть к этому, когда я захочу использовать python. Есть ли способ получить хи-квадрат из фита? Потому что подгонка бесполезна, если не знать ее качества.

Machiel Kolstein 14.12.2020 10:02

Другие вопросы по теме